From 50fd2e13cfdedd9c94ed6236d2ea4392de8e640a Mon Sep 17 00:00:00 2001 From: Aleksandr Kuzminsky Date: Tue, 28 Feb 2017 18:06:59 -0800 Subject: [PATCH 1/2] fixes issue #11 --- tests/unit/conftest.py | 803 ++++++++++++++++++++++++ tests/unit/test_twindb_table_compare.py | 31 +- twindb_table_compare/compare.py | 19 +- 3 files changed, 851 insertions(+), 2 deletions(-) create mode 100644 tests/unit/conftest.py diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py new file mode 100644 index 0000000..2721721 --- /dev/null +++ b/tests/unit/conftest.py @@ -0,0 +1,803 @@ +import pytest + + +@pytest.fixture +def out_master(): + return """*************************** 1. row *************************** + Host: localhost + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 2. row *************************** + Host: master.box + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 3. row *************************** + Host: 127.0.0.1 + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 4. row *************************** + Host: ::1 + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 5. row *************************** + Host: localhost + User: + Password: + Select_priv: N + Insert_priv: N + Update_priv: N + Delete_priv: N + Create_priv: N + Drop_priv: N + Reload_priv: N + Shutdown_priv: N + Process_priv: N + File_priv: N + Grant_priv: N + References_priv: N + Index_priv: N + Alter_priv: N + Show_db_priv: N + Super_priv: N + Create_tmp_table_priv: N + Lock_tables_priv: N + Execute_priv: N + Repl_slave_priv: N + Repl_client_priv: N + Create_view_priv: N + Show_view_priv: N + Create_routine_priv: N + Alter_routine_priv: N + Create_user_priv: N + Event_priv: N + Trigger_priv: N +Create_tablespace_priv: N + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: NULL + password_expired: N +*************************** 6. row *************************** + Host: master.box + User: + Password: + Select_priv: N + Insert_priv: N + Update_priv: N + Delete_priv: N + Create_priv: N + Drop_priv: N + Reload_priv: N + Shutdown_priv: N + Process_priv: N + File_priv: N + Grant_priv: N + References_priv: N + Index_priv: N + Alter_priv: N + Show_db_priv: N + Super_priv: N + Create_tmp_table_priv: N + Lock_tables_priv: N + Execute_priv: N + Repl_slave_priv: N + Repl_client_priv: N + Create_view_priv: N + Show_view_priv: N + Create_routine_priv: N + Alter_routine_priv: N + Create_user_priv: N + Event_priv: N + Trigger_priv: N +Create_tablespace_priv: N + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: NULL + password_expired: N +*************************** 7. row *************************** + Host: % + User: dba + Password: *AA1420F182E88B9E5F874F6FBE7459291E8F4601 + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 8. row *************************** + Host: localhost + User: dba + Password: *AA1420F182E88B9E5F874F6FBE7459291E8F4601 + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 9. row *************************** + Host: % + User: repl + Password: *809534247D21AC735802078139D8A854F45C31F3 + Select_priv: N + Insert_priv: N + Update_priv: N + Delete_priv: N + Create_priv: N + Drop_priv: N + Reload_priv: N + Shutdown_priv: N + Process_priv: N + File_priv: N + Grant_priv: N + References_priv: N + Index_priv: N + Alter_priv: N + Show_db_priv: N + Super_priv: N + Create_tmp_table_priv: N + Lock_tables_priv: N + Execute_priv: N + Repl_slave_priv: Y + Repl_client_priv: N + Create_view_priv: N + Show_view_priv: N + Create_routine_priv: N + Alter_routine_priv: N + Create_user_priv: N + Event_priv: N + Trigger_priv: N +Create_tablespace_priv: N + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +""", "" + + +@pytest.fixture +def out_slave(): + return """*************************** 1. row *************************** + Host: localhost + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 2. row *************************** + Host: slave.box + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 3. row *************************** + Host: 127.0.0.1 + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 4. row *************************** + Host: ::1 + User: root + Password: + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 5. row *************************** + Host: localhost + User: + Password: + Select_priv: N + Insert_priv: N + Update_priv: N + Delete_priv: N + Create_priv: N + Drop_priv: N + Reload_priv: N + Shutdown_priv: N + Process_priv: N + File_priv: N + Grant_priv: N + References_priv: N + Index_priv: N + Alter_priv: N + Show_db_priv: N + Super_priv: N + Create_tmp_table_priv: N + Lock_tables_priv: N + Execute_priv: N + Repl_slave_priv: N + Repl_client_priv: N + Create_view_priv: N + Show_view_priv: N + Create_routine_priv: N + Alter_routine_priv: N + Create_user_priv: N + Event_priv: N + Trigger_priv: N +Create_tablespace_priv: N + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: NULL + password_expired: N +*************************** 6. row *************************** + Host: slave.box + User: + Password: + Select_priv: N + Insert_priv: N + Update_priv: N + Delete_priv: N + Create_priv: N + Drop_priv: N + Reload_priv: N + Shutdown_priv: N + Process_priv: N + File_priv: N + Grant_priv: N + References_priv: N + Index_priv: N + Alter_priv: N + Show_db_priv: N + Super_priv: N + Create_tmp_table_priv: N + Lock_tables_priv: N + Execute_priv: N + Repl_slave_priv: N + Repl_client_priv: N + Create_view_priv: N + Show_view_priv: N + Create_routine_priv: N + Alter_routine_priv: N + Create_user_priv: N + Event_priv: N + Trigger_priv: N +Create_tablespace_priv: N + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: NULL + password_expired: N +*************************** 7. row *************************** + Host: % + User: dba + Password: *AA1420F182E88B9E5F874F6FBE7459291E8F4601 + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 8. row *************************** + Host: localhost + User: dba + Password: *AA1420F182E88B9E5F874F6FBE7459291E8F4601 + Select_priv: Y + Insert_priv: Y + Update_priv: Y + Delete_priv: Y + Create_priv: Y + Drop_priv: Y + Reload_priv: Y + Shutdown_priv: Y + Process_priv: Y + File_priv: Y + Grant_priv: Y + References_priv: Y + Index_priv: Y + Alter_priv: Y + Show_db_priv: Y + Super_priv: Y + Create_tmp_table_priv: Y + Lock_tables_priv: Y + Execute_priv: Y + Repl_slave_priv: Y + Repl_client_priv: Y + Create_view_priv: Y + Show_view_priv: Y + Create_routine_priv: Y + Alter_routine_priv: Y + Create_user_priv: Y + Event_priv: Y + Trigger_priv: Y +Create_tablespace_priv: Y + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +*************************** 9. row *************************** + Host: % + User: repl + Password: *809534247D21AC735802078139D8A854F45C31F3 + Select_priv: N + Insert_priv: N + Update_priv: N + Delete_priv: N + Create_priv: N + Drop_priv: N + Reload_priv: N + Shutdown_priv: N + Process_priv: N + File_priv: N + Grant_priv: N + References_priv: N + Index_priv: N + Alter_priv: N + Show_db_priv: N + Super_priv: N + Create_tmp_table_priv: N + Lock_tables_priv: N + Execute_priv: N + Repl_slave_priv: Y + Repl_client_priv: N + Create_view_priv: N + Show_view_priv: N + Create_routine_priv: N + Alter_routine_priv: N + Create_user_priv: N + Event_priv: N + Trigger_priv: N +Create_tablespace_priv: N + ssl_type: + ssl_cipher: + x509_issuer: + x509_subject: + max_questions: 0 + max_updates: 0 + max_connections: 0 + max_user_connections: 0 + plugin: mysql_native_password + authentication_string: + password_expired: N +""", "" diff --git a/tests/unit/test_twindb_table_compare.py b/tests/unit/test_twindb_table_compare.py index 1eac759..b1c9de6 100644 --- a/tests/unit/test_twindb_table_compare.py +++ b/tests/unit/test_twindb_table_compare.py @@ -15,7 +15,7 @@ from click.testing import CliRunner from twindb_table_compare import cli, __version__ -from twindb_table_compare.compare import is_printable, diff +from twindb_table_compare.compare import is_printable, diff, print_vertical def test_command_line_interface(): @@ -639,3 +639,32 @@ def test_diff(master_lines, slave_lines, difference): actual_diff = diff(master_lines, slave_lines) assert actual_diff == difference + + +@mock.patch('twindb_table_compare.compare.Popen') +def test_print_vertical(mock_popen, out_master, out_slave): + mock_proc = mock.Mock() + mock_proc.communicate.side_effect = [out_master, out_slave] + mock_proc.returncode = 0 + + mock_popen.return_value = mock_proc + assert print_vertical('foo1', 'foo2', 'foo3', 'foo4', 'foo5', + color=False) == """@@ -43,7 +43,7 @@ + authentication_string: + password_expired: N + ************************************************************** +- Host: master.box ++ Host: slave.box + User: root + Password: + Select_priv: Y +@@ -219,7 +219,7 @@ + authentication_string: NULL + password_expired: N + ************************************************************** +- Host: master.box ++ Host: slave.box + User: + Password: + Select_priv: N +""" diff --git a/twindb_table_compare/compare.py b/twindb_table_compare/compare.py index e936a22..7ceda44 100644 --- a/twindb_table_compare/compare.py +++ b/twindb_table_compare/compare.py @@ -403,6 +403,14 @@ def print_vertical(master, slave, user, passwd, query, color=True): '-e', r'%s\G' % query], stdout=PIPE, stderr=PIPE) master_cout, master_cerr = proc.communicate() + master_lines = [] + for line in master_cout.split('\n'): + if line.startswith('***************************'): + master_lines.append('*******************************' + '*******************************') + else: + master_lines.append(line) + if proc.returncode: LOG.error('Failed to query master.') LOG.error(master_cerr) @@ -413,12 +421,21 @@ def print_vertical(master, slave, user, passwd, query, color=True): '-e', r'%s\G' % query], stdout=PIPE, stderr=PIPE) slave_cout, slave_cerr = proc.communicate() + + slave_lines = [] + for line in slave_cout.split('\n'): + if line.startswith('***************************'): + slave_lines.append('*******************************' + '*******************************') + else: + slave_lines.append(line) + if proc.returncode: LOG.error('Failed to query slave.') LOG.error(slave_cerr) exit(1) - return diff(master_cout.split('\n'), slave_cout.split('\n'), color=color) + return diff(master_lines, slave_lines, color=color) def get_inconsistencies(db, tbl, slave, user, passwd, From a4b0946c683901149880f6f55e07f3156f6a2e23 Mon Sep 17 00:00:00 2001 From: Aleksandr Kuzminsky Date: Tue, 28 Feb 2017 18:08:17 -0800 Subject: [PATCH 2/2] =?UTF-8?q?Bump=20version:=201.1.1=20=E2=86=92=201.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.cfg | 2 +- setup.py | 2 +- twindb_table_compare/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index ed0b4ca..317b7a2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.1.1 +current_version = 1.1.2 commit = True tag = False diff --git a/setup.py b/setup.py index fca2332..ecac8b1 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ setup( name='twindb_table_compare', - version='1.1.1', + version='1.1.2', description="TwinDB Table Compare reads percona.checksums from the master " "and slave and shows what records are difference " "if there are any inconsistencies.", diff --git a/twindb_table_compare/__init__.py b/twindb_table_compare/__init__.py index 67a9f98..9520eaf 100644 --- a/twindb_table_compare/__init__.py +++ b/twindb_table_compare/__init__.py @@ -8,7 +8,7 @@ __author__ = 'Aleksandr Kuzminsky' __email__ = 'aleks@twindb.com' -__version__ = '1.1.1' +__version__ = '1.1.2' LOG = logging.getLogger(__name__)