# ==== Purpose ====
#
# Test that the slave fails to connect to the master with
# MASTER_AUTO_POSITION=1 if the slave is missing some transactions
# that the master has purged.
#
# ==== Implementation ====
#
# 1) Create a master-slave setup.
# 2) Create a table on master, sync it, stop the slave threads and dump thread
#    on master.
# 3) On master, generate a transaction, flush the binary log and execute PURGE
#    BINARY LOGS TO command so that only remaining binlog only contains
#    transaction UUID:3.
# 4) Verify that the slave fails if it tries to connect using CHANGE MASTER TO
#    MASTER_AUTO_POSITION=1.
# 5) Verify that appropriate messages are logged into master's and slave's
#    error log.
# 6) Verify that replication succeeds if it tries to connect using CHANGE
#    MASTER TO MASTER_LOG_POS.
# 7) Cleanup.
#
# ==== References ====
#
# WL#3584 - Global Transaction Identifiers
# Bug#29769293 - ERROR 1236 "MASTER HAS PURGED BINARY LOGS CONTAINING GTIDS":
#                GTID NOT LOGGED

--source include/not_group_replication_plugin.inc
--source include/have_debug.inc
--source include/have_gtid.inc
--let $rpl_gtid_utils= 1

--echo #
--echo # 1) Create a master-slave setup.
--echo #
--source include/master-slave.inc

--let $master_uuid= `SELECT @@SERVER_UUID`

--echo #
--echo # 2) Create a table on master, sync it, stop the slave threads and dump
--echo #    thread on master.
--echo #
CREATE TABLE t1 (a INT) ENGINE = InnoDB;
--source include/sync_slave_sql_with_master.inc
--source include/stop_slave.inc

--source include/rpl_connection_master.inc
# Need to kill the dump thread explicitly: stop slave does not do
# that, and if the dump thread is slow, it will still be reading from
# the old binlog at the time we do PURGE BINARY LOGS below. That would
# prevent PURGE BINARY LOGS from purging the log.
--source include/stop_dump_threads.inc

--echo #
--echo # 3) On master, generate a transaction, flush the binary log and execute
--echo #    PURGE BINARY LOGS TO command so that only remaining binlog only contains
--echo #    transaction UUID:3.
--echo #
INSERT INTO t1 VALUES (1);

FLUSH LOGS;
--let $master_file= query_get_value(SHOW MASTER STATUS, File, 1)
--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
INSERT INTO t1 VALUES (2);
--save_master_pos

--eval PURGE BINARY LOGS TO '$master_file'

--let $assert_cond= "[SHOW MASTER STATUS, File, 1]" = "$master_file"
--let $assert_text= PURGE BINARY LOGS successfully removed all but the latest file
--source include/assert.inc

--echo #
--echo # 4) Verify that the slave fails if it tries to connect using CHANGE
--echo #    MASTER TO MASTER_AUTO_POSITION=1.
--echo #
--source include/rpl_connection_slave.inc
CHANGE MASTER TO MASTER_AUTO_POSITION = 1;

START SLAVE;

# BUG#13727933 causes this test to fail sporadically on the following line
# apparently the binlog is not always purged on the master (?)
--let $slave_io_errno= 1236 # ER_MASTER_FATAL_ERROR_READING_BINLOG
--source include/wait_for_slave_io_error.inc
--source include/stop_slave_sql.inc

# Testing with long set of gtids
--source include/rpl_connection_master.inc
SET @saved_debug= @@GLOBAL.DEBUG;
SET GLOBAL DEBUG= '+d,simulate_long_missing_gtids';
--source include/rpl_connection_slave.inc
START SLAVE;

--let $slave_io_errno= 1236 # ER_MASTER_FATAL_ERROR_READING_BINLOG
--source include/wait_for_slave_io_error.inc
--source include/stop_slave_sql.inc
--source include/rpl_connection_master.inc
SET GLOBAL DEBUG= @saved_debug;
--source include/rpl_connection_slave.inc

--echo #
--echo # 5) Verify that appropriate messages are logged into master's and slave's
--echo #    error log.
--echo #

# Verify that suggestions to extract the missing gtids are logged into the master's error log.
--let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.1.err
--let $assert_match= .*To find the missing purged transactions.*
--let $assert_select= To find the missing purged transactions
--let $assert_text= Found the suggestions to extract the missing GTIDs in the master error log.
--source include/assert_grep.inc

# Verify that an error about long gtids are logged into the slave's error log.
--let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.2.err
--let $assert_match= .*The GTID sets and the missing purged transactions are too long to print in this message.*
--let $assert_select= The GTID sets and the missing purged transactions are too long to print in this message.
--let $assert_text= Found a message about the long GTIDs in the slave error log.
--source include/assert_grep.inc

--echo #
--echo # 6) Verify that replication succeeds if it tries to connect using CHANGE
--echo #    MASTER TO MASTER_LOG_POS.
--echo #
--replace_result $master_file MASTER_FILE $master_pos MASTER_POS
eval CHANGE MASTER TO MASTER_LOG_FILE = '$master_file', MASTER_LOG_POS = $master_pos, MASTER_AUTO_POSITION = 0;

--source include/start_slave.inc
--sync_with_master

--let $assert_text= t1 should contain only one row with the value 2
--let $assert_cond= "[SELECT COUNT(*) FROM t1]" = "1" AND "[SELECT * FROM t1]" = "2"
--source include/assert.inc
--source include/stop_slave.inc

# Verify that warning about the missing transactions are logged into the master's error log.
--let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.1.err
--let $assert_match= .*Cannot replicate to server with server_uuid.*The missing transactions are '.*:2'.*
--let $assert_select= Cannot replicate to server with server_uuid
--let $assert_text= Found warning containing lost GTIDs in the master error log.
--source include/assert_grep.inc

# Verify that an error about the missing transactions are logged into the slave's error log.
--let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.2.err
--let $assert_match= .*Replicate the missing transactions from elsewhere, or provision a new slave from backup.*the missing transactions are '.*:2'.*
--let $assert_select= Replicate the missing transactions from elsewhere, or provision a new slave from backup
--let $assert_text= Found warning containing lost GTIDs in the slave error log.
--source include/assert_grep.inc

# Suppress the error on master.
--source include/rpl_connection_master.inc
CALL mtr.add_suppression("Cannot replicate to server.*server has purged required binary logs.*");

# Suppress the error on slave.
--source include/rpl_connection_slave.inc
CALL mtr.add_suppression("Got fatal error 1236 from master.*Replicate the missing transactions from elsewhere");

--echo #
--echo # 7) Cleanup.
--echo #
--source include/rpl_connection_slave.inc
RESET MASTER;
RESET SLAVE;
--source include/rpl_connection_master.inc
RESET MASTER;
--source include/rpl_connection_slave.inc
--source include/start_slave.inc
--source include/rpl_connection_master.inc
DROP TABLE t1;
--source include/sync_slave_sql_with_master.inc
--source include/rpl_end.inc
