/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.internal.runner.app.jdbc;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import static java.sql.Connection.TRANSACTION_NONE;
import static java.sql.Connection.TRANSACTION_READ_COMMITTED;
import static java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
import static java.sql.Connection.TRANSACTION_REPEATABLE_READ;
import static java.sql.Connection.TRANSACTION_SERIALIZABLE;
import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT;
import static java.sql.ResultSet.CONCUR_READ_ONLY;
import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
import static java.sql.Statement.NO_GENERATED_KEYS;
import static java.sql.Statement.RETURN_GENERATED_KEYS;
import static org.apache.ignite.client.proto.query.SqlStateCode.TRANSACTION_STATE_EXCEPTION;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

/**
 * Connection test.
 */
@SuppressWarnings("ThrowableNotThrown")
public class ITJdbcConnectionSelfTest extends AbstractJdbcSelfTest {
    /**
     * @throws Exception If failed.
     */
    @SuppressWarnings({"EmptyTryBlock", "unused"})
    @Test
    public void testDefaults() throws Exception {
        var url = "jdbc:ignite:thin://127.0.1.1:10800";

        try (Connection conn = DriverManager.getConnection(url)) {
            // No-op.
        }

        try (Connection conn = DriverManager.getConnection(url + "/")) {
            // No-op.
        }
    }

    /**
     * @throws Exception If failed.
     */
    @SuppressWarnings({"EmptyTryBlock", "unused"})
    @Test
    @Disabled("ITDS-1887")
    public void testDefaultsIPv6() throws Exception {
        var url = "jdbc:ignite:thin://[::1]:10800";

        try (Connection conn = DriverManager.getConnection(url)) {
            // No-op.
        }

        try (Connection conn = DriverManager.getConnection(url + "/")) {
            // No-op.
        }
    }

    /**
     * Test invalid endpoint.
     */
    @Test
    public void testInvalidEndpoint() {
        assertInvalid("jdbc:ignite:thin://", "Address is empty");
        assertInvalid("jdbc:ignite:thin://:10000", "Host name is empty");
        assertInvalid("jdbc:ignite:thin://     :10000", "Host name is empty");

        assertInvalid("jdbc:ignite:thin://127.0.0.1:-1", "port range contains invalid port -1");
        assertInvalid("jdbc:ignite:thin://127.0.0.1:0", "port range contains invalid port 0");
        assertInvalid("jdbc:ignite:thin://127.0.0.1:100000",
            "port range contains invalid port 100000");

        assertInvalid("jdbc:ignite:thin://[::1]:-1", "port range contains invalid port -1");
        assertInvalid("jdbc:ignite:thin://[::1]:0", "port range contains invalid port 0");
        assertInvalid("jdbc:ignite:thin://[::1]:100000",
            "port range contains invalid port 100000");
    }

    /**
     * Test schema property in URL.
     *
     * @throws Exception If failed.
     */
    @Test
    public void testSchema() throws Exception {
        assertInvalid(URL + "/qwe/qwe",
            "Invalid URL format (only schema name is allowed in URL path parameter 'host:port[/schemaName]')" );

        try (Connection conn = DriverManager.getConnection(URL + "/public")) {
            assertEquals( "PUBLIC", conn.getSchema(), "Invalid schema");
        }

        String dfltSchema = "DEFAULT";

        try (Connection conn = DriverManager.getConnection(URL + "/\"" + dfltSchema + '"')) {
            assertEquals(dfltSchema, conn.getSchema(), "Invalid schema");
        }

        try (Connection conn = DriverManager.getConnection(URL + "/_not_exist_schema_")) {
            assertEquals("_NOT_EXIST_SCHEMA_", conn.getSchema(), "Invalid schema");
        }
    }

    /**
     * Test schema property in URL with semicolon.
     *
     * @throws Exception If failed.
     */
    @Test
    public void testSchemaSemicolon() throws Exception {
        String dfltSchema = "DEFAULT";

        try (Connection conn = DriverManager.getConnection(URL + ";schema=public")) {
            assertEquals("PUBLIC", conn.getSchema(), "Invalid schema");
        }

        try (Connection conn =
                 DriverManager.getConnection(URL + ";schema=\"" + dfltSchema + '"')) {
            assertEquals( dfltSchema, conn.getSchema(), "Invalid schema");
        }

        try (Connection conn = DriverManager.getConnection(URL + ";schema=_not_exist_schema_")) {
            assertEquals("_NOT_EXIST_SCHEMA_", conn.getSchema(), "Invalid schema");
        }
    }

    /**
     * Assert that provided URL is invalid.
     *
     * @param url URL.
     * @param errMsg Error message.
     */
    private void assertInvalid(final String url, String errMsg) {
        assertThrows(SQLException.class, () -> DriverManager.getConnection(url), errMsg);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testClose() throws Exception {
        final Connection conn;

        try (Connection conn0 = DriverManager.getConnection(URL)) {
            conn = conn0;

            assertNotNull(conn);
            assertFalse(conn.isClosed());
        }

        assertTrue(conn.isClosed());

        assertFalse(conn.isValid(2), "Connection must be closed");

        assertThrows(SQLException.class, () -> conn.isValid(-2), "Invalid timeout");
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCreateStatement() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            try (Statement stmt = conn.createStatement()) {
                assertNotNull(stmt);

                stmt.close();

                conn.close();

                // Exception when called on closed connection
                checkConnectionClosed(() -> conn.createStatement());
            }
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testCreateStatement2() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            int[] rsTypes = new int[]
                {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE};

            int[] rsConcurs = new int[]
                {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE};

            DatabaseMetaData meta = conn.getMetaData();

            for (final int type : rsTypes) {
                for (final int concur : rsConcurs) {
                    if (meta.supportsResultSetConcurrency(type, concur)) {
                        assertEquals(TYPE_FORWARD_ONLY, type);
                        assertEquals(CONCUR_READ_ONLY, concur);

                        try (Statement stmt = conn.createStatement(type, concur)) {
                            assertNotNull(stmt);

                            assertEquals(type, stmt.getResultSetType());
                            assertEquals(concur, stmt.getResultSetConcurrency());
                        }

                        continue;
                    }

                    assertThrows(SQLFeatureNotSupportedException.class, () -> conn.createStatement(type, concur));
                }
            }

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.createStatement(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY));
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testCreateStatement3() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            int[] rsTypes = new int[]
                {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE};

            int[] rsConcurs = new int[]
                {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE};

            int[] rsHoldabilities = new int[]
                {HOLD_CURSORS_OVER_COMMIT, CLOSE_CURSORS_AT_COMMIT};

            DatabaseMetaData meta = conn.getMetaData();

            for (final int type : rsTypes) {
                for (final int concur : rsConcurs) {
                    for (final int holdabililty : rsHoldabilities) {
                        if (meta.supportsResultSetConcurrency(type, concur)) {
                            assertEquals(TYPE_FORWARD_ONLY, type);
                            assertEquals(CONCUR_READ_ONLY, concur);

                            try (Statement stmt = conn.createStatement(type, concur, holdabililty)) {
                                assertNotNull(stmt);

                                assertEquals(type, stmt.getResultSetType());
                                assertEquals(concur, stmt.getResultSetConcurrency());
                                assertEquals(holdabililty, stmt.getResultSetHoldability());
                            }

                            continue;
                        }

                        assertThrows(SQLFeatureNotSupportedException.class, 
                            () -> conn.createStatement(type, concur, holdabililty));
                    }
                }
            }

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.createStatement(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT));
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testPrepareStatement() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // null query text
            assertThrows(
                NullPointerException.class,
                () -> conn.prepareStatement(null)
            );

            final String sqlText = "select * from test where param = ?";

            try (PreparedStatement prepared = conn.prepareStatement(sqlText)) {
                assertNotNull(prepared);
            }

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.prepareStatement(sqlText));
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testPrepareStatement3() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            final String sqlText = "select * from test where param = ?";

            int[] rsTypes = new int[]
                {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE};

            int[] rsConcurs = new int[]
                {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE};

            DatabaseMetaData meta = conn.getMetaData();

            for (final int type : rsTypes) {
                for (final int concur : rsConcurs) {
                    if (meta.supportsResultSetConcurrency(type, concur)) {
                        assertEquals(TYPE_FORWARD_ONLY, type);
                        assertEquals(CONCUR_READ_ONLY, concur);

                        // null query text
                        assertThrows(
                            SQLException.class,
                            () -> conn.prepareStatement(null, type, concur),
                            "SQL string cannot be null"
                        );

                        continue;
                    }

                    assertThrows(
                        SQLFeatureNotSupportedException.class,
                        () -> conn.prepareStatement(sqlText, type, concur)
                    );
                }
            }

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.prepareStatement(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY));

            conn.close();
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testPrepareStatement4() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            final String sqlText = "select * from test where param = ?";

            int[] rsTypes = new int[]
                {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE};

            int[] rsConcurs = new int[]
                {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE};

            int[] rsHoldabilities = new int[]
                {HOLD_CURSORS_OVER_COMMIT, CLOSE_CURSORS_AT_COMMIT};

            DatabaseMetaData meta = conn.getMetaData();

            for (final int type : rsTypes) {
                for (final int concur : rsConcurs) {
                    for (final int holdabililty : rsHoldabilities) {
                        if (meta.supportsResultSetConcurrency(type, concur)) {
                            assertEquals(TYPE_FORWARD_ONLY, type);
                            assertEquals(CONCUR_READ_ONLY, concur);

                            // null query text
                            assertThrows(
                                SQLException.class,
                                () -> conn.prepareStatement(null, type, concur, holdabililty),
                                "SQL string cannot be null"
                            );

                            continue;
                        }

                        assertThrows(
                            SQLFeatureNotSupportedException.class,
                            () -> conn.prepareStatement(sqlText, type, concur, holdabililty)
                        );
                    }
                }
            }

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(
                () -> conn.prepareStatement(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT)
            );

            conn.close();
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testPrepareStatementAutoGeneratedKeysUnsupported() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            final String sqlText = "insert into test (val) values (?)";

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.prepareStatement(sqlText, RETURN_GENERATED_KEYS),
                "Auto generated keys are not supported."
            );

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.prepareStatement(sqlText, NO_GENERATED_KEYS),
                "Auto generated keys are not supported."
            );

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.prepareStatement(sqlText, new int[] {1}),
                "Auto generated keys are not supported."
            );

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.prepareStatement(sqlText, new String[] {"ID"}),
                "Auto generated keys are not supported."
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testPrepareCallUnsupported() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            final String sqlText = "exec test()";

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.prepareCall(sqlText),
                "Callable functions are not supported."
            );

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.prepareCall(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY),
                "Callable functions are not supported."
            );

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.prepareCall(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT),
                "Callable functions are not supported."
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testNativeSql() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // null query text
            assertThrows(
                NullPointerException.class,
                () -> conn.nativeSQL(null)
            );

            final String sqlText = "select * from test";

            assertEquals(sqlText, conn.nativeSQL(sqlText));

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.nativeSQL(sqlText));
        }
    }

    /**
     * TODO Enable when transactions are ready.
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testGetSetAutoCommit() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            boolean ac0 = conn.getAutoCommit();

            conn.setAutoCommit(!ac0);
            // assert no exception

            conn.setAutoCommit(ac0);
            // assert no exception

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.setAutoCommit(ac0));
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCommit() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Should not be called in auto-commit mode
            assertThrows(
                SQLException.class,
                () -> conn.commit(),
                "Transaction cannot be committed explicitly in auto-commit mode"
            );

            assertTrue(conn.getAutoCommit());

            // Should not be called in auto-commit mode
            assertThrows(
                SQLException.class,
                () -> conn.commit(),
                "Transaction cannot be committed explicitly in auto-commit mode."
            );

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.commit());
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testRollback() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Should not be called in auto-commit mode
            assertThrows(
                SQLException.class,
                () -> conn.rollback(),
                "Transaction cannot be rolled back explicitly in auto-commit mode."
            );

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.rollback());
        }
    }

    /**
     * Enable when transactions are ready.
     *
     * @throws Exception if failed.
     */
    @Test
    @Disabled
    public void testBeginFailsWhenMvccIsDisabled() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            conn.createStatement().execute("BEGIN");

            fail("Exception is expected");
        }
        catch (SQLException e) {
            assertEquals(TRANSACTION_STATE_EXCEPTION, e.getSQLState());
        }
    }

    /**
     * Enable when transactions are ready.
     *
     * @throws Exception if failed.
     */
    @Test
    @Disabled
    public void testCommitIgnoredWhenMvccIsDisabled() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            conn.setAutoCommit(false);
            conn.createStatement().execute("COMMIT");

            conn.commit();
        }
        // assert no exception
    }

    /**
     * Enable when transactions are ready.
     *
     * @throws Exception if failed.
     */
    @Test
    @Disabled
    public void testRollbackIgnoredWhenMvccIsDisabled() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            conn.setAutoCommit(false);

            conn.createStatement().execute("ROLLBACK");

            conn.rollback();
        }
        // assert no exception
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testGetMetaData() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            DatabaseMetaData meta = conn.getMetaData();

            assertNotNull(meta);

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.getMetaData());
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testGetSetReadOnly() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.setReadOnly(true));

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.isReadOnly());
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testGetSetCatalog() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            assertFalse(conn.getMetaData().supportsCatalogsInDataManipulation());

            assertNull(conn.getCatalog());

            conn.setCatalog("catalog");

            assertNull(conn.getCatalog());

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.setCatalog(""));

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.getCatalog());
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testGetSetTransactionIsolation() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Invalid parameter value
            assertThrows(
                SQLException.class,
                () -> conn.setTransactionIsolation(-1),
                "Invalid transaction isolation level"
            );

            // default level
            assertEquals(TRANSACTION_NONE, conn.getTransactionIsolation());

            int[] levels = {
                TRANSACTION_READ_UNCOMMITTED, TRANSACTION_READ_COMMITTED,
                TRANSACTION_REPEATABLE_READ, TRANSACTION_SERIALIZABLE};

            for (int level : levels) {
                conn.setTransactionIsolation(level);
                assertEquals(level, conn.getTransactionIsolation());
            }

            conn.close();

            // Exception when called on closed connection

            checkConnectionClosed(() -> conn.getTransactionIsolation());

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.setTransactionIsolation(TRANSACTION_SERIALIZABLE));
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testClearGetWarnings() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            SQLWarning warn = conn.getWarnings();

            assertNull(warn);

            conn.clearWarnings();

            warn = conn.getWarnings();

            assertNull(warn);

            conn.close();

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.getWarnings());

            // Exception when called on closed connection
            checkConnectionClosed(() -> conn.clearWarnings());
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testGetSetTypeMap() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.getTypeMap(),
                "Types mapping is not supported"
            );

            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.setTypeMap(new HashMap<String, Class<?>>()),
                "Types mapping is not supported"
            );
            
            conn.close();
            
            // Exception when called on closed connection

            assertThrows(
                SQLException.class,
                () -> conn.getTypeMap(),
                "Connection is closed"
            );

            assertThrows(
                SQLException.class,
                () -> conn.setTypeMap(new HashMap<String, Class<?>>()),
                "Connection is closed"
            );
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testGetSetHoldability() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // default value
            assertEquals(conn.getMetaData().getResultSetHoldability(), conn.getHoldability());

            assertEquals(HOLD_CURSORS_OVER_COMMIT, conn.getHoldability());

            conn.setHoldability(CLOSE_CURSORS_AT_COMMIT);

            assertEquals(CLOSE_CURSORS_AT_COMMIT, conn.getHoldability());

            // Invalid constant
            
            assertThrows(
                SQLException.class,
                () -> conn.setHoldability(-1),
                "Invalid result set holdability value"
            );

            conn.close();

            assertThrows(
                SQLException.class,
                () -> conn.getHoldability(),
                "Connection is closed"
            );

            assertThrows(
                SQLException.class,
                () -> conn.setHoldability(HOLD_CURSORS_OVER_COMMIT),
                "Connection is closed"
            );
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testSetSavepoint() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            assertFalse(conn.getMetaData().supportsSavepoints());

            // Disallowed in auto-commit mode
            assertThrows(
                SQLException.class,
                () -> conn.setSavepoint(),
                "Savepoint cannot be set in auto-commit mode"
            );

            conn.close();

            checkConnectionClosed(() -> conn.setSavepoint());
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testSetSavepointName() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            assertFalse(conn.getMetaData().supportsSavepoints());

            // Invalid arg
            assertThrows(
                SQLException.class,
                () -> conn.setSavepoint(null),
                "Savepoint name cannot be null"
            );

            final String name = "savepoint";

            // Disallowed in auto-commit mode
            assertThrows(
                SQLException.class,
                () -> conn.setSavepoint(name),
                "Savepoint cannot be set in auto-commit mode"
            );

            conn.close();

            checkConnectionClosed(() -> conn.setSavepoint(name));
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testRollbackSavePoint() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            assertFalse(conn.getMetaData().supportsSavepoints());

            // Invalid arg
            assertThrows(
                SQLException.class,
                () -> conn.rollback(null),
                "Invalid savepoint"
            );

            final Savepoint savepoint = getFakeSavepoint();

            // Disallowed in auto-commit mode
            assertThrows(
                SQLException.class,
                () -> conn.rollback(savepoint),
                "Auto-commit mode"
            );

            conn.close();

            checkConnectionClosed(() -> conn.rollback(savepoint));
        }
    }

    /**
     * TODO  IGNITE-15188
     *
     * @throws Exception If failed.
     */
    @Test
    @Disabled
    public void testReleaseSavepoint() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            assertFalse(conn.getMetaData().supportsSavepoints());

            // Invalid arg
            assertThrows(
                SQLException.class,
                () -> conn.releaseSavepoint(null),
                "Savepoint cannot be null"
            );

            final Savepoint savepoint = getFakeSavepoint();

            checkNotSupported(() -> conn.releaseSavepoint(savepoint));

            conn.close();

            checkConnectionClosed(() -> conn.releaseSavepoint(savepoint));
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCreateClob() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Unsupported
            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.createClob(),
                "SQL-specific types are not supported"
            );

            conn.close();

            assertThrows(
                SQLException.class,
                () -> conn.createClob(),
                "Connection is closed"
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCreateBlob() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Unsupported
            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.createBlob(),
                "SQL-specific types are not supported"
            );

            conn.close();

            assertThrows(
                SQLException.class,
                () -> conn.createBlob(),
                "Connection is closed"
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCreateNClob() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Unsupported
            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.createNClob(),
                "SQL-specific types are not supported"
            );

            conn.close();

            assertThrows(
                SQLException.class,
                () -> conn.createNClob(),
                "Connection is closed"
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCreateSQLXML() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Unsupported
            assertThrows(
                SQLFeatureNotSupportedException.class,
                () -> conn.createSQLXML(),
                "SQL-specific types are not supported"
            );

            conn.close();

            assertThrows(
                SQLException.class,
                () -> conn.createSQLXML(),
                "Connection is closed"
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testGetSetClientInfoPair() throws Exception {
//        fail("https://issues.apache.org/jira/browse/IGNITE-5425");

        try (Connection conn = DriverManager.getConnection(URL)) {
            final String name = "ApplicationName";
            final String val = "SelfTest";

            assertNull(conn.getWarnings());

            conn.setClientInfo(name, val);

            assertNull(conn.getClientInfo(val));

            conn.close();

            checkConnectionClosed(() -> conn.getClientInfo(name));

            assertThrows(
                SQLClientInfoException.class,
                () -> conn.setClientInfo(name, val),
                "Connection is closed"
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testGetSetClientInfoProperties() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            final String name = "ApplicationName";
            final String val = "SelfTest";

            final Properties props = new Properties();
            props.setProperty(name, val);

            conn.setClientInfo(props);

            Properties propsResult = conn.getClientInfo();

            assertNotNull(propsResult);

            assertTrue(propsResult.isEmpty());

            conn.close();

            checkConnectionClosed(() -> conn.getClientInfo());

            assertThrows(
                SQLClientInfoException.class,
                () -> conn.setClientInfo(props),
                "Connection is closed"
            );
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCreateArrayOf() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            final String typeName = "varchar";

            final String[] elements = new String[] {"apple", "pear"};

            // Invalid typename
            assertThrows(
                SQLException.class,
                () -> conn.createArrayOf(null, null),
                "Type name cannot be null"
            );

            // Unsupported

            checkNotSupported(() -> conn.createArrayOf(typeName, elements));

            conn.close();

            checkConnectionClosed(() -> conn.createArrayOf(typeName, elements));
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCreateStruct() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // Invalid typename
            assertThrows(
                SQLException.class,
                () -> conn.createStruct(null, null),
                "Type name cannot be null"
            );

            final String typeName = "employee";

            final Object[] attrs = new Object[] {100, "Tom"};

            checkNotSupported(() -> conn.createStruct(typeName, attrs));

            conn.close();

            checkConnectionClosed(() -> conn.createStruct(typeName, attrs));
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testGetSetSchema() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            assertEquals("PUBLIC", conn.getSchema());

            final String schema = "test";

            conn.setSchema(schema);

            assertEquals(schema.toUpperCase(), conn.getSchema());

            conn.setSchema('"' + schema + '"');

            assertEquals(schema, conn.getSchema());

            conn.close();

            checkConnectionClosed(() -> conn.setSchema(schema));

            checkConnectionClosed(() -> conn.getSchema());
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testAbort() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            //Invalid executor
            assertThrows(
                SQLException.class,
                () -> conn.abort(null),
                "Executor cannot be null"
            );

            final Executor executor = Executors.newFixedThreadPool(1);

            conn.abort(executor);

            assertTrue(conn.isClosed());
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testGetSetNetworkTimeout() throws Exception {
        try (Connection conn = DriverManager.getConnection(URL)) {
            // default
            assertEquals(0, conn.getNetworkTimeout());

            final Executor executor = Executors.newFixedThreadPool(1);

            final int timeout = 1000;

            //Invalid timeout
            assertThrows(
                SQLException.class,
                () -> conn.setNetworkTimeout(executor, -1),
                "Network timeout cannot be negative"
            );

            conn.setNetworkTimeout(executor, timeout);

            assertEquals(timeout, conn.getNetworkTimeout());

            conn.close();

            checkConnectionClosed(() -> conn.getNetworkTimeout());

            checkConnectionClosed(() -> conn.setNetworkTimeout(executor, timeout));
        }
    }

    /**
     * @return Savepoint.
     */
    private Savepoint getFakeSavepoint() {
        return new Savepoint() {
            @Override public int getSavepointId() throws SQLException {
                return 100;
            }

            @Override public String getSavepointName() {
                return "savepoint";
            }
        };
    }
}
