--skip # Test unstable on jenkins
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/not_valgrind.inc
--source include/not_embedded.inc

--let $error_log=$MYSQL_TMP_DIR/my_restart.err
--let $restart_parameters=restart:--innodb-encryption-threads=0 --log-error=$error_log
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
--source include/restart_mysqld.inc

CREATE TABLE t1 (a VARCHAR(255)) ENGINE=InnoDB;
CREATE TABLE t2 (a VARCHAR(255)) ENGINE=InnoDB;
CREATE TABLE t3 (a VARCHAR(255)) ENGINE=InnoDB;
CREATE TABLE t4 (a VARCHAR(255)) ENGINE=InnoDB;

insert t1 values (repeat('foobarsecret', 12));
insert t2 values (repeat('tempsecret', 12));
insert t3 values (repeat('dummysecret', 12));
insert t4 values (repeat('verysecret', 12));

--let $assert_text= Make sure all tables have encrypted flag disabled
--let $assert_cond= "[SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ((FLAG & 8192) = 8192)]" = 0
--source include/assert.inc

--echo # We should encrypt all tables apart from t3
SET GLOBAL debug="+d,fail_encryption_flag_update_on_t3";

--echo # Enable encryption
SET GLOBAL innodb_encryption_rotate_key_age=15;
SET GLOBAL innodb_encryption_threads = 4;
SET GLOBAL innodb_encrypt_tables = ONLINE_TO_KEYRING;

--echo # Wait for all tables to get encrypted
--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB' and table_schema <> 'information_schema'`
--let $wait_timeout= 600
# Encrypted tables count should be equal $tables_count - because INNODB_TABLESPACES_ENCRYPTION
# contains an artificial table innodb_system and t3 should not be encrypted
--let $wait_condition=SELECT COUNT(*) = $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 1
--source include/wait_condition.inc

--let $assert_text= Make sure only t3's encryption flag is not set
--let $assert_cond= "[SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ((FLAG & 8192) = 0)]" = "test/t3"
--source include/assert.inc

--echo # Disable encryption
SET GLOBAL innodb_encryption_threads = 0;
SET GLOBAL debug="-d,fail_encryption_flag_update_on_t3";

--source include/shutdown_mysqld.inc

--echo # Check that error message about t3 being removed from encryption rotation is present in error log
--let SEARCH_PATTERN=Encryption thread failed to flush encryption information for tablespace test/t3. This should not happen and could indicate problem with OS or filesystem. Excluding test/t3 from encryption rotation. You can try decrypting/encrypting with alter statement for this table or restarting the server.
--let ABORT_ON=NOT_FOUND
--let SEARCH_FILE=$error_log
--source include/search_pattern_in_file.inc

--remove_file $error_log

--echo # On restart all tables with encrypted flag set should get validated against Data Dictionary. Let's check there is
--echo # no error related to encryption flag mismatch between DD and ibd file.
--let $restart_parameters=restart:--innodb-encryption-threads=0 --log-error=$error_log
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
--source include/start_mysqld.inc

SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
SELECT * FROM t4;

--let $assert_text= Make sure only t3's encryption flag is not set
--let $assert_cond= "[SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ((FLAG & 8192) = 0)]" = "test/t3"
--source include/assert.inc

--source include/shutdown_mysqld.inc
--let SEARCH_PATTERN=This indicates that the rotation of the table was interrupted
--let ABORT_ON=FOUND
--let SEARCH_FILE=$error_log
--source include/search_pattern_in_file.inc

--remove_file $error_log

--let $restart_parameters=restart:--innodb-encryption-threads=4 --innodb-encrypt-tables=ONLINE_TO_KEYRING
--source include/start_mysqld.inc

--echo # Wait for all tables to get encrypted
--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB' and table_schema <> 'information_schema'`
--let $wait_timeout= 600
# Encrypted tables count should be equal $tables_count + 1 - because INNODB_TABLESPACES_ENCRYPTION
# contains an artificial table innodb_system
--let $wait_condition=SELECT COUNT(*) = $tables_count + 1 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 1
--source include/wait_condition.inc

--let $assert_text= Make sure all tablespaces have encryption flag set
--let $assert_cond= "[SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ((FLAG & 8192) = 0)]" = 0
--source include/assert.inc


--let $error_log2=$MYSQL_TMP_DIR/my_restart2.err
--let $restart_parameters=restart:--innodb-encryption-threads=0 --innodb-encrypt-tables=ONLINE_FROM_KEYRING_TO_UNENCRYPTED --log-error=$error_log2
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
--source include/restart_mysqld.inc

DROP TABLE t1,t2,t3,t4;

--echo # Recreate t1..t4 inside a tablespace

CREATE TABLESPACE ts_1 ADD DATAFILE 'ts_1.ibd' ENGINE="InnoDB";
CREATE TABLE t1 (a varchar(255)) TABLESPACE ts_1 ENGINE="InnoDB";
CREATE TABLE t2 (a varchar(255)) TABLESPACE ts_1 ENGINE="InnoDB";
CREATE TABLE t3 (a varchar(255)) TABLESPACE ts_1 ENGINE="InnoDB";
CREATE TABLE t4 (a varchar(255)) TABLESPACE ts_1 ENGINE="InnoDB";

# The purpose of t5 is bit weird. We want to catch the situation when ts_1 rotation has failed due
# to t3 flush problem. So ts_1 should remain marked as unencrypted in this part. How do we know that
# the flush problem occurred if we do not have debug sync point here? We will use only one encryption
# thread and t5 will be processed after ts_1. We will wait for t5 to get encrypted and thus we will know
# that t3's flush problem should have occurred.
CREATE TABLE t5 (a varchar(255)) ENGINE="InnoDB";

insert t1 values (repeat('foobarsecret', 12));
insert t2 values (repeat('tempsecret', 12));
insert t3 values (repeat('dummysecret', 12));
insert t4 values (repeat('verysecret', 12));

--let $assert_text= Make sure ts_1's encryption flag is not set
--let $assert_cond= "[SELECT FLAG & 8192 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE NAME =\\'test/ts_1\\']" = 0
--source include/assert.inc

--echo # Since t3 flag's update will fail, the tablespace ts_1's flag should remain unencrypted
SET GLOBAL debug="+d,fail_encryption_flag_update_on_t3";

--echo # Enable encryption
SET GLOBAL innodb_encryption_rotate_key_age=15;
SET GLOBAL innodb_encryption_threads = 1;
SET GLOBAL innodb_encrypt_tables = ONLINE_TO_KEYRING;

--echo # Wait for all tables to get encrypted (apart from ts_1)
--let $tablespaces_count= `select count(*) from information_schema.innodb_sys_tablespaces`
--let $wait_timeout= 600
# Encrypted tablespaces count should be equal $tables_count - because INNODB_TABLESPACES_ENCRYPTION
# contains an artificial tablespace innodb_system and ts_1 should not be encrypted
--let $wait_condition=SELECT COUNT(*) = $tablespaces_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 1
--source include/wait_condition.inc

--echo # Disable encryption
SET GLOBAL innodb_encryption_threads = 0;
SET GLOBAL debug="-d,fail_encryption_flag_update_on_t3";

--let $assert_text= Make sure only ts_1's encryption flag is not set
--let $assert_cond= "[SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ((FLAG & 8192) = 0)]" = "ts_1"
--source include/assert.inc

--source include/shutdown_mysqld.inc

--echo # Check that error message about ts_1 being removed from encryption rotation is present in error log
--let SEARCH_PATTERN=Encryption thread failed to flush encryption information for tablespace ts_1. This should not happen and could indicate problem with OS or filesystem. Excluding ts_1 from encryption rotation. You can try decrypting/encrypting with alter statement for this table or restarting the server.
--let ABORT_ON=NOT_FOUND
--let SEARCH_FILE=$error_log2
--source include/search_pattern_in_file.inc

--remove_file $error_log2

--echo # On restart all tables with encrypted flag set should get validated against Data Dictionary. Let's check there is
--echo # no error related to encryption flag mismatch between DD and ibd file.

--let $restart_parameters=restart:--innodb-encryption-threads=0 --log-error=$error_log
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
--source include/start_mysqld.inc

SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
SELECT * FROM t4;

--let $assert_text= Make sure only ts_1's encryption flag is not set
--let $assert_cond= "[SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ((FLAG & 8192) = 0)]" = "ts_1"
--source include/assert.inc

--source include/shutdown_mysqld.inc
--let SEARCH_PATTERN=This indicates that the rotation of the table was interrupted
--let ABORT_ON=FOUND
--let SEARCH_FILE=$error_log
--source include/search_pattern_in_file.inc

--echo # Turn ON encryption and check that ts_1 gets successfully encrypted after the restart.

--let $restart_parameters=restart:--innodb-encryption-threads=4 --innodb-encrypt-tables=ONLINE_TO_KEYRING
--source include/start_mysqld.inc

--echo # Wait for all tables to get encrypted
--let $tablespaces_count= `select count(*) from information_schema.innodb_sys_tablespaces`
--let $wait_timeout= 600
# Encrypted tablespaces count should be equal $tables_count + 1 because INNODB_TABLESPACES_ENCRYPTION
# contains an artificial tablespace innodb_system
--let $wait_condition=SELECT COUNT(*) = $tablespaces_count + 1 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 1
--source include/wait_condition.inc

--let $assert_text= Make sure all tablespaces have encryption flag set
--let $assert_cond= "[SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE ((FLAG & 8192) = 0)]" = 0
--source include/assert.inc

DROP TABLE t1,t2,t3,t4;
DROP TABLESPACE ts_1;
