package org.mariadb.jdbc.failover; import org.junit.Assume; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mariadb.jdbc.internal.util.constant.HaMode; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; public class ReplicationFailoverTest extends BaseReplication { /** * Initialisation. * * @throws SQLException exception */ @BeforeClass() public static void beforeClass2() throws SQLException { proxyUrl = proxyReplicationUrl; Assume.assumeTrue(initialReplicationUrl != null); } /** * Initialisation. * * @throws SQLException exception */ @Before public void init() throws SQLException { defaultUrl = initialReplicationUrl; currentType = HaMode.REPLICATION; } @Test public void readOnlyPropagatesToServerAlias() throws SQLException { assureReadOnly(true); } @Test public void assureReadOnly() throws SQLException { assureReadOnly(false); } /** * Test assureReadOnly / readOnlyPropagatesToServer alias. * * @param useAlias use alias readOnlyPropagatesToServer ? * @throws SQLException if any exception */ public void assureReadOnly(boolean useAlias) throws SQLException { try (Connection connection = getNewConnection(useAlias ? "&readOnlyPropagatesToServer=true" : "&assureReadOnly=true", false)) { Statement stmt = connection.createStatement(); stmt.execute("drop table if exists replicationDelete" + jobId); stmt.execute("create table replicationDelete" + jobId + " (id int not null primary key auto_increment, test VARCHAR(10))"); connection.setReadOnly(true); assertTrue(connection.isReadOnly()); try { if (!isMariaDbServer(connection) || !requireMinimumVersion(connection, 5, 7)) { //on version >= 5.7 use SESSION READ-ONLY, before no control Assume.assumeTrue(false); } connection.createStatement().execute("drop table if exists replicationDelete" + jobId); fail(); } catch (SQLException e) { //normal exception } } } @Test public void pingReconnectAfterFailover() throws Throwable { try (Connection connection = getNewConnection("&retriesAllDown=6&connectTimeout=1000&socketTimeout=1000", true)) { Statement st = connection.createStatement(); final int masterServerId = getServerId(connection); stopProxy(masterServerId); try { st.execute("SELECT 1"); } catch (SQLException e) { //normal exception } connection.setReadOnly(true); st = connection.createStatement(); restartProxy(masterServerId); try { connection.setReadOnly(false); } catch (SQLException e) { fail(); } } } @Test public void failoverDuringMasterSetReadOnly() throws Throwable { try (Connection connection = getNewConnection("&retriesAllDown=6&connectTimeout=1000&socketTimeout=1000", true)) { int masterServerId = getServerId(connection); stopProxy(masterServerId); connection.setReadOnly(true); int slaveServerId = getServerId(connection); assertFalse(slaveServerId == masterServerId); assertTrue(connection.isReadOnly()); } } @Test() public void masterWithoutFailover() throws Throwable { try (Connection connection = getNewConnection("&retriesAllDown=6&connectTimeout=1000&socketTimeout=1000", true)) { int masterServerId = getServerId(connection); connection.setReadOnly(true); int firstSlaveId = getServerId(connection); connection.setReadOnly(false); stopProxy(masterServerId); stopProxy(firstSlaveId); try { connection.createStatement().executeQuery("SELECT CONNECTION_ID()"); fail(); } catch (SQLException e) { assertTrue(true); } } } @Test public void checkBackOnMasterOnSlaveFail() throws Throwable { try (Connection connection = getNewConnection( "&retriesAllDown=6&failOnReadOnly=true&connectTimeout=1000&socketTimeout=1000", true)) { Statement st = connection.createStatement(); int masterServerId = getServerId(connection); stopProxy(masterServerId); try { st.execute("SELECT 1"); assertTrue(connection.isReadOnly()); } catch (SQLException e) { fail(); } long stoppedTime = System.nanoTime(); restartProxy(masterServerId); boolean loop = true; while (loop) { Thread.sleep(250); try { connection.setReadOnly(true); loop = false; } catch (SQLException e) { //eat exception } long duration = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - stoppedTime); if (duration > 15 * 1000) { fail(); } } } } @Test public void testFailNotOnSlave() throws Throwable { try (Connection connection = getNewConnection("&retriesAllDown=6&connectTimeout=1000&socketTimeout=1000", true)) { Statement stmt = connection.createStatement(); int masterServerId = getServerId(connection); stopProxy(masterServerId); try { stmt.execute("SELECT 1"); fail(); } catch (SQLException e) { //normal error } assertTrue(!connection.isReadOnly()); } } }