1#!/usr/bin/env perl 2 3BEGIN { 4 die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" 5 unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; 6 unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; 7}; 8 9use strict; 10use warnings FATAL => 'all'; 11use English qw(-no_match_vars); 12use Test::More; 13 14# Hostnames make testing less accurate. Tests need to see 15# that such-and-such happened on specific slave hosts, but 16# the sandbox servers are all on one host so all slaves have 17# the same hostname. 18$ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} = 1; 19 20use Data::Dumper; 21use PerconaTest; 22use Sandbox; 23 24# Fix @INC because pt-table-checksum uses subclass OobNibbleIterator. 25require "$trunk/bin/pt-table-checksum"; 26 27my $dp = new DSNParser(opts=>$dsn_opts); 28my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); 29my $master_dbh = $sb->get_dbh_for('master'); 30my $slave1_dbh = $sb->get_dbh_for('slave1'); 31my $slave2_dbh = $sb->get_dbh_for('slave2'); 32 33if ( !$master_dbh ) { 34 plan skip_all => 'Cannot connect to sandbox master'; 35} 36elsif ( !$slave1_dbh ) { 37 plan skip_all => 'Cannot connect to sandbox slave1'; 38} 39elsif ( !@{$master_dbh->selectall_arrayref("show databases like 'sakila'")} ) { 40 plan skip_all => 'sakila database is not loaded'; 41} 42 43# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic 44# so we need to specify --set-vars innodb_lock_wait_timeout=3 else the tool will die. 45my $master_dsn = 'h=127.1,P=12345'; 46my @args = (qw(--set-vars innodb_lock_wait_timeout=3)); 47my $row; 48my $output; 49my $exit_status; 50my $sample = "t/pt-table-checksum/samples/"; 51 52# ############################################################################ 53# Should always create schema and tables with IF NOT EXISTS 54# https://bugs.launchpad.net/percona-toolkit/+bug/950294 55# ############################################################################ 56 57$master_dbh->do("DROP DATABASE IF EXISTS percona"); 58diag(`/tmp/12345/use -u root < $trunk/t/lib/samples/ro-checksum-user.sql 2>/dev/null`); 59PerconaTest::wait_for_table($slave2_dbh, "mysql.user", "user='ro_checksum_user'"); 60 61$output = output( 62 sub { $exit_status = pt_table_checksum::main(@args, 63 "$master_dsn,u=ro_checksum_user,p=msandbox", 64 qw(--recursion-method none) 65 ) }, 66 stderr => 1, 67); 68 69like( 70 $output, 71 qr/\Qdatabase percona does not exist and it cannot be created automatically/, 72 "Error if percona db doesn't exist and user can't create it", 73); 74 75$output = output( 76 sub { pt_table_checksum::main(@args, 77 "$master_dsn,u=ro_checksum_user,p=msandbox", 78 qw(--recursion-method none --no-create-replicate-table) 79 ) }, 80 stderr => 1, 81); 82 83like( 84 $output, 85 qr/\Qdatabase percona does not exist and --no-create-replicate-table was/, 86 "Error if percona db doesn't exist and --no-create-replicate-table", 87); 88 89diag(`/tmp/12345/use -u root -e "drop user 'ro_checksum_user'\@'%'"`); 90wait_until( 91 sub { 92 my $rows=$slave2_dbh->selectall_arrayref("SELECT user FROM mysql.user"); 93 return !grep { ($_->[0] || '') eq 'ro_checksum_user' } @$rows; 94 } 95); 96 97# ############################################################################ 98# --recursion-method=none to avoid SHOW SLAVE HOSTS 99# https://bugs.launchpad.net/percona-toolkit/+bug/987694 100# ############################################################################ 101 102# Create percona.checksums because ro_checksum_user doesn't have the privs. 103pt_table_checksum::main(@args, 104 "$master_dsn,u=msandbox,p=msandbox", 105 qw(-t sakila.country --quiet --quiet)); 106 107diag(`/tmp/12345/use -u root < $trunk/t/lib/samples/ro-checksum-user.sql 2>/dev/null`); 108PerconaTest::wait_for_table($slave1_dbh, "mysql.tables_priv", "user='ro_checksum_user'"); 109 110$output = output( 111 sub { $exit_status = pt_table_checksum::main(@args, 112 "$master_dsn,u=ro_checksum_user,p=msandbox", 113 # Comment out this line and the tests fail because ro_checksum_user 114 # doesn't have privs to SHOW SLAVE HOSTS. This proves that 115 # --recursion-method none is working. 116 qw(--recursion-method none --no-create-replicate-table) 117 ) }, 118 stderr => 1, 119); 120 121is( 122 $exit_status, 123 0, 124 "Read-only user (bug 987694): 0 exit" 125); 126 127like( 128 $output, 129 qr/ sakila.store$/m, 130 "Read-only user (bug 987694): checksummed rows" 131); 132 133($output, $exit_status) = full_output( 134 sub { pt_table_checksum::main(@args, 135 "$master_dsn,u=ro_checksum_user,p=msandbox", 136 qw(--recursion-method none) 137 ) } 138); 139 140is( 141 $exit_status, 142 0, 143 "No error if db exists on the master, can't CREATE DATABASE, --no-create-replicate-table was not specified, but the database does exist in all slaves" 144); 145 146diag(qx{/tmp/12345/use -u root -e 'DROP TABLE `percona`.`checksums`'}); 147 148($output, $exit_status) = full_output( 149 sub { pt_table_checksum::main(@args, 150 "$master_dsn,u=ro_checksum_user,p=msandbox", 151 qw(--recursion-method none --no-create-replicate-table) 152 ) }, 153); 154 155like($output, 156 qr/\Q--replicate table `percona`.`checksums` does not exist and --no/, 157 "Error if checksums db doesn't exist and --no-create-replicate-table" 158); 159 160diag(`/tmp/12345/use -u root -e "drop user 'ro_checksum_user'\@'%'"`); 161wait_until( 162 sub { 163 my $rows=$slave2_dbh->selectall_arrayref("SELECT user FROM mysql.user"); 164 return !grep { ($_->[0] || '') eq 'ro_checksum_user' } @$rows; 165 } 166); 167 168# ############################################################################# 169# Bug 916168: bug in pt-table-checksum privileges check 170# ############################################################################# 171diag(`/tmp/12345/use -u root < $trunk/t/pt-table-checksum/samples/privs-bug-916168.sql`); 172 173$output = output( 174 sub { $exit_status = pt_table_checksum::main(@args, 175 "$master_dsn,u=test_user,p=foo", qw(-t sakila.country)) }, 176); 177 178is( 179 PerconaTest::count_checksum_results($output, 'rows'), 180 109, 181 "test_user privs work (bug 916168)" 182); 183 184diag(`/tmp/12345/use -u root -e "drop user 'test_user'\@'%'"`); 185wait_until( 186 sub { 187 my $rows=$slave2_dbh->selectall_arrayref("SELECT user FROM mysql.user"); 188 return !grep { ($_->[0] || '') eq 'test_user' } @$rows; 189 } 190); 191 192# ############################################################################# 193# Done. 194# ############################################################################# 195$sb->wipe_clean($master_dbh); 196ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); 197done_testing; 198exit; 199