############################################################
# Purpose: WL#5064 Testing with corrupted events.
# The test emulates the corruption at the vary stages
# of replication:
#  - in binlog file
#  - in network
#  - in relay log
############################################################

#
# The tests intensively utilize @@global.debug. Note,
# Bug#11765758 - 58754,
# @@global.debug is read by the slave threads through dbug-interface. 
# Hence, before a client thread set @@global.debug we have to ensure that:
# (a) the slave threads are stopped, or (b) the slave threads are in
# sync and waiting.

--source include/have_debug.inc
--source include/master-slave.inc

# Block legal errors for MTR 
call mtr.add_suppression('Found invalid event in binary log');
call mtr.add_suppression('Slave I/O: Relay log write failure: could not queue event from master');
call mtr.add_suppression('event read from binlog did not pass crc check');
call mtr.add_suppression('Replication event checksum verification failed');
call mtr.add_suppression('Event crc check failed! Most likely there is event corruption');
call mtr.add_suppression('Slave SQL: Error initializing relay log position: I/O error reading event at position .*, Error_code: 1593');

SET @old_master_verify_checksum = @@master_verify_checksum;

# Creating test table/data and set corruption position for testing
--echo # 1. Creating test table/data and set corruption position for testing
--connection master
--echo * insert/update/delete rows in table t1 *
# Corruption algorithm modifies only the first event and 
# then will be reset. To avoid checking always the first event 
# from binlog (usually it is FD) we randomly execute different 
# statements and set position for corruption inside events.

CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c VARCHAR(100));
--disable_query_log
let $i=`SELECT 3+CEILING(10*RAND())`;
let $j=1;
let $pos=0;
while ($i) {  
  eval INSERT INTO t1 VALUES ($j, 'a', NULL);
  if (`SELECT RAND() > 0.7`)
  {
    eval UPDATE t1 SET c = REPEAT('a', 20) WHERE a = $j;
  }
  if (`SELECT RAND() > 0.8`)
  {
    eval DELETE FROM t1 WHERE a = $j;
  }
  if (!$pos) {
    let $pos= query_get_value(SHOW MASTER STATUS, Position, 1);
    --source include/sync_slave_sql_with_master.inc
    --source include/stop_slave.inc
    --disable_query_log
    --connection master
  }
  dec $i;
  inc $j;
}
--enable_query_log


# Emulate corruption in binlog file when SHOW BINLOG EVENTS is executing
--echo # 2. Corruption in master binlog and SHOW BINLOG EVENTS
SET GLOBAL debug="d,corrupt_read_log_event_char";
--echo SHOW BINLOG EVENTS;
--disable_query_log
send_eval SHOW BINLOG EVENTS FROM $pos;
--enable_query_log
--error ER_ERROR_WHEN_EXECUTING_COMMAND
reap;

# Emulate corruption on master with crc checking on master
--echo # 3. Master read a corrupted event from binlog and send the error to slave
SET GLOBAL debug="d,corrupt_read_log_event";
--connection slave
START SLAVE IO_THREAD;
let $slave_io_errno= 1236; # ER_MASTER_FATAL_ERROR_READING_BINLOG
--source include/wait_for_slave_io_error.inc
--connection master

# Emulate corruption on master without crc checking on master
--echo # 4. Master read a corrupted event from binlog and send it to slave
--connection master
SET GLOBAL master_verify_checksum=0;
SET GLOBAL debug="d,corrupt_read_log_event";
--connection slave
START SLAVE IO_THREAD;
let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
--source include/wait_for_slave_io_error.inc
--connection master
SET GLOBAL debug="";
SET GLOBAL master_verify_checksum=1;

# Emulate corruption in network
--echo # 5. Slave. Corruption in network
--connection slave
SET GLOBAL debug="d,corrupt_queue_event";
START SLAVE IO_THREAD;
let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
--source include/wait_for_slave_io_error.inc

# Emulate corruption in relay log
--echo # 6. Slave. Corruption in relay log
SET GLOBAL debug="d,corrupt_read_log_event_char";
START SLAVE SQL_THREAD;
let $slave_sql_errno= 1593; # ER_SLAVE_FATAL_ERROR
--source include/wait_for_slave_sql_error.inc

# Start normal replication and compare same table on master
# and slave
--echo # 7. Seek diff for tables on master and slave
--connection slave
SET GLOBAL debug= "";
--source include/start_slave.inc
--connection master
--source include/sync_slave_sql_with_master.inc
--let $diff_tables= master:t1, slave:t1
--source include/diff_tables.inc
                                                               
# Clean up
--echo # 8. Clean up
--connection master
SET GLOBAL master_verify_checksum = @old_master_verify_checksum;
DROP TABLE t1;
--source include/sync_slave_sql_with_master.inc

--source include/rpl_end.inc
