Files
percona-toolkit/t/lib/RowDiff.t
Sveta Smirnova 9755074cd8 PT-2156 Fix tests for lib, part2 (#650)
* PT-2156 - Fix tests for lib

Fixed tests, broken by putting fix for PT-1554 into the library code, mostly by updating checksums.
Added AutoCommit option for test lib/QueryReview.t
Reset SQL mode to empty to allow TableChunker to work with invalid and zero dates

* PT-2156 - Fix tests for lib

Adjusted t/lib/SchemaIterator.t to work with version 8.0

* PT-2156 - Fix tests for lib

Adjusted b/t/lib/Processlist.t, so it reflects fix for PT-981

* PT-2156 - Fix tests for lib

Adjusted t/lib/HTTP/Micro.t, so it works with different order of parameters, returned at v.percona.com/
Adjusted test for empty files in t/lib/bash/collect.t
Disabled mysqladmin debug test in t/lib/bash/collect.t, because of PT-2242

* PT-2156 - Fix tests for lib

Added LC_NUMERRIC=POSIX into t/lib/bash/report_system_info.sh, so reports in tests are not environment-dependent
Updated expected results in t/lib/bash/report_system_info.sh, so they reflect new information, collected by pt-summary

* PT-2156 - Fix tests for lib

- Improved fix for PT-76, so it handles inline comments
- Added test case for PT-76
- Improved fix for PT-1720, so it ignores unrecognizable option only if it comes from the toolkit-wide files and still errors out if wrong option was passed via command line or the tool-specific option file.

* PT-2156 - Fix tests for lib

- Improved fix for PT-2102, so it finds running instance configuration file using PID and also does not break t/lib/bash/report_mysql_info.t test
- Removed unnecessary copy-paste from t/pt-mysql-summary/pt-2102.t test
- Adjusted number of collected files in t/lib/bash/collect_mysql_info.sh

* PT-2156 - Fix tests for lib

- Fix for PT-1543 and MyRocks collection were originally put only into lib/bash/report_mysql_info.shthat broke the logic of collecting data first, then formatting report from this data. This, in its turn, broke test t/lib/bash/report_mysql_info.sh/t/lib/bash/report_mysql_info.t, because CMD_MYSQL is not defined in this library. I rewrote these fixes, so they follow original logic of the tool (pt-mysql-summary)
- Added tests for keyring plugin, encrypted tables, and MyRocks for t/lib/bash/report_mysql_info.sh and t/pt-mysql-summary/pt-mysql-summary_encryption.t

* PT-2156 - Fix tests for lib

- Added FLUSH TABLES to t/lib/bash/collect.sh, so it does not fail opentables tests if run when more than 1000 tables open in the sandbox environment
- Changed number of expected sample files to reflect keyring colletion file

* PT-2156 - Fix tests for lib

- Added skip to some tests in lib that file when run with PXC, because not supported to work with PXC
- Adjusted configuration files for PXC, so they allow LOAD DATA/SELECT INTO OUTFILE commands
- Adjusted data samples, so they do not depend on auto increment values
- Fixed lib tests, failing with PXC

* PT-2156 - Fix tests for lib

Updated tests for pt-online-schema-change, so they work with PXC and skipped if designed for semi-synchronous replication setup

* PT-2156 - Fix tests for lib

- Added cluster-specific samples for t/lib/SchemaIterator.t
- Removed extra debugging print from t/pt-table-checksum/pt-1728.t

* PT-2156 - Fix tests for lib

Evgeniy's review on July 20

* Update t/lib/TableSyncer.t

Removed comment left after debugging

* Update t/pt-mysql-summary/pt-mysql-summary_encryption.t

Removed extra debug output

* PT-2156 - Fix tests for lib

Tabs to spaces
2023-08-02 14:50:21 +03:00

556 lines
12 KiB
Perl

#!/usr/bin/env perl
BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use MockSync;
use RowDiff;
use MockSth;
use Sandbox;
use DSNParser;
use TableParser;
use Quoter;
use PerconaTest;
my ($d, $s);
my $q = new Quoter();
my $tp = new TableParser(Quoter => $q);
my $dp = new DSNParser(opts=>$dsn_opts);
# Connect to sandbox now to make sure it's running.
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $master_dbh = $sb->get_dbh_for('master');
my $slave_dbh = $sb->get_dbh_for('slave1');
throws_ok( sub { new RowDiff() }, qr/I need a dbh/, 'DBH required' );
$d = new RowDiff(dbh => 1);
# #############################################################################
# Test key_cmp().
# #############################################################################
my %args = (
key_cols => [qw(a)],
tbl_struct => {},
);
is(
$d->key_cmp(
lr => { a => 1 },
rr => { a => 1 },
%args,
),
0,
'Equal keys',
);
is(
$d->key_cmp(
lr => { a => undef },
rr => { a => undef },
%args,
),
0,
'Equal null keys',
);
is(
$d->key_cmp(
lr => undef,
rr => { a => 1 },
%args,
),
-1,
'Left key missing',
);
is(
$d->key_cmp(
lr => { a => 1 },
rr => undef,
%args,
),
1,
'Right key missing',
);
is(
$d->key_cmp(
lr => { a => 2 },
rr => { a => 1 },
%args,
),
1,
'Right key smaller',
);
is(
$d->key_cmp(
lr => { a => 2 },
rr => { a => 3 },
%args,
),
-1,
'Right key larger',
);
$args{key_cols} = [qw(a b)];
is(
$d->key_cmp(
lr => { a => 1, b => 2, },
rr => { a => 1, b => 1 },
%args,
),
1,
'Right two-part key smaller',
);
is(
$d->key_cmp(
lr => { a => 1, b => 0, },
rr => { a => 1, b => 1 },
%args,
),
-1,
'Right two-part key larger',
);
is(
$d->key_cmp(
lr => { a => 1, b => undef, },
rr => { a => 1, b => 1 },
%args,
),
-1,
'Right two-part key larger because of null',
);
is(
$d->key_cmp(
lr => { a => 1, b => 0, },
rr => { a => 1, b => undef },
%args,
),
1,
'Left two-part key larger because of null',
);
is(
$d->key_cmp(
lr => { a => 1, b => 0, },
rr => { a => undef, b => 1 },
%args,
),
1,
'Left two-part key larger because of null in first key part',
);
# #############################################################################
# Test compare_sets() using a mock syncer.
# #############################################################################
$s = new MockSync();
$d->compare_sets(
left_sth => new MockSth(),
right_sth => new MockSth(),
syncer => $s,
tbl_struct => {},
);
is_deeply(
$s,
[
'done',
],
'no rows',
);
$s = new MockSync();
$d->compare_sets(
left_sth => new MockSth(
),
right_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
),
syncer => $s,
tbl_struct => {},
);
is_deeply(
$s,
[
[ 'not in left', { a => 1, b => 2, c => 3 },],
'done',
],
'right only',
);
$s = new MockSync();
$d->compare_sets(
left_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
),
right_sth => new MockSth(
),
syncer => $s,
tbl_struct => {},
);
is_deeply(
$s,
[
[ 'not in right', { a => 1, b => 2, c => 3 },],
'done',
],
'left only',
);
$s = new MockSync();
$d->compare_sets(
left_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
),
right_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
),
syncer => $s,
tbl_struct => {},
);
is_deeply(
$s,
[
'same',
'done',
],
'one identical row',
);
$s = new MockSync();
$d->compare_sets(
left_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
{ a => 2, b => 2, c => 3 },
{ a => 3, b => 2, c => 3 },
# { a => 4, b => 2, c => 3 },
),
right_sth => new MockSth(
# { a => 1, b => 2, c => 3 },
{ a => 2, b => 2, c => 3 },
{ a => 3, b => 2, c => 3 },
{ a => 4, b => 2, c => 3 },
),
syncer => $s,
tbl_struct => {},
);
is_deeply(
$s,
[
[ 'not in right', { a => 1, b => 2, c => 3 }, ],
'same',
'same',
[ 'not in left', { a => 4, b => 2, c => 3 }, ],
'done',
],
'differences in basic set of rows',
);
$s = new MockSync();
$d->compare_sets(
left_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
),
right_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
),
syncer => $s,
tbl_struct => { is_numeric => { a => 1 } },
);
is_deeply(
$s,
[
'same',
'done',
],
'Identical with numeric columns',
);
SKIP: {
skip 'Cannot connect to sandbox master', 1 unless $master_dbh;
$d = new RowDiff(dbh => $master_dbh);
$s = new MockSync();
$d->compare_sets(
left_sth => new MockSth(
{ a => 'A', b => 2, c => 3 },
),
right_sth => new MockSth(
# The difference is the lowercase 'a', which in a _ci collation will
# sort the same. So the rows are really identical, from MySQL's point
# of view.
{ a => 'a', b => 2, c => 3 },
),
syncer => $s,
tbl_struct => { collation_for => { a => 'utf8mb4_general_ci' } },
);
is_deeply(
$s,
[
'same',
'done',
],
'Identical with utf8 columns',
);
}
# #############################################################################
# Test that the callbacks work.
# #############################################################################
my @rows;
my $same_row = sub {
push @rows, 'same row';
};
my $not_in_left = sub {
push @rows, 'not in left';
};
my $not_in_right = sub {
push @rows, 'not in right';
};
my $key_cmp = sub {
my ( $col, $lr, $rr ) = @_;
push @rows, "col $col differs";
};
$s = new MockSync();
$d = new RowDiff(
dbh => 1,
key_cmp => $key_cmp,
same_row => $same_row,
not_in_left => $not_in_left,
not_in_right => $not_in_right,
);
@rows = ();
$d->compare_sets(
left_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
{ a => 2, b => 2, c => 3 },
{ a => 3, b => 2, c => 3 },
# { a => 4, b => 2, c => 3 },
),
right_sth => new MockSth(
# { a => 1, b => 2, c => 3 },
{ a => 2, b => 2, c => 3 },
{ a => 3, b => 2, c => 3 },
{ a => 4, b => 2, c => 3 },
),
syncer => $s,
tbl_struct => {},
);
is_deeply(
\@rows,
[
'col a differs',
'not in right',
'same row',
'same row',
'not in left',
],
'callbacks'
);
my $i = 0;
$d = new RowDiff(
dbh => 1,
key_cmp => $key_cmp,
same_row => $same_row,
not_in_left => $not_in_left,
not_in_right => $not_in_right,
done => sub { return ++$i > 2 ? 1 : 0; },
);
@rows = ();
$d->compare_sets(
left_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
{ a => 2, b => 2, c => 3 },
{ a => 3, b => 2, c => 3 },
# { a => 4, b => 2, c => 3 },
),
right_sth => new MockSth(
# { a => 1, b => 2, c => 3 },
{ a => 2, b => 2, c => 3 },
{ a => 3, b => 2, c => 3 },
{ a => 4, b => 2, c => 3 },
),
syncer => $s,
tbl_struct => {},
);
is_deeply(
\@rows,
[
'col a differs',
'not in right',
'same row',
'same row',
],
'done callback'
);
$d = new RowDiff(
dbh => 1,
key_cmp => $key_cmp,
same_row => $same_row,
not_in_left => $not_in_left,
not_in_right => $not_in_right,
trf => sub {
my ( $l, $r, $tbl, $col ) = @_;
return 1, 1; # causes all rows to look like they're identical
},
);
@rows = ();
$d->compare_sets(
left_sth => new MockSth(
{ a => 1, b => 2, c => 3 },
{ a => 4, b => 5, c => 6 },
),
right_sth => new MockSth(
{ a => 7, b => 8, c => 9 },
{ a => 10, b => 11, c => 12 },
),
syncer => $s,
tbl_struct => { is_numeric => { a => 1, b => 1, c => 1 } },
);
is_deeply(
\@rows,
[
'same row',
'same row',
],
'trf callback'
);
# #############################################################################
# The following tests use "real" (sandbox) servers and real statement handles.
# #############################################################################
SKIP: {
skip 'Cannot connect to sandbox master', 4 unless $master_dbh;
skip 'Cannot connect to sandbox slave', 4 unless $slave_dbh;
PXC_SKIP: {
skip 'Not for PXC' if ( $sb->is_cluster_mode );
$d = new RowDiff(dbh => $master_dbh);
$sb->create_dbs($master_dbh, [qw(test)]);
$sb->load_file('master', 't/lib/samples/issue_11.sql');
PerconaTest::wait_until(
sub {
my $r;
eval {
$r = $slave_dbh->selectrow_arrayref('SHOW TABLES FROM test LIKE "issue_11"');
};
return 1 if ($r->[0] || '') eq 'issue_11';
return 0;
},
0.25,
30,
);
my $tbl = $tp->parse(
$tp->get_create_table($master_dbh, 'test', 'issue_11'));
my $left_sth = $master_dbh->prepare('SELECT * FROM test.issue_11');
my $right_sth = $slave_dbh->prepare('SELECT * FROM test.issue_11');
$left_sth->execute();
$right_sth->execute();
$s = new MockSync();
$d->compare_sets(
left_sth => $left_sth,
right_sth => $right_sth,
syncer => $s,
tbl_struct => $tbl,
);
is_deeply(
$s,
['done',],
'no rows (real DBI sth)',
);
$slave_dbh->do('INSERT INTO test.issue_11 VALUES (1,2,3)');
$left_sth = $master_dbh->prepare('SELECT * FROM test.issue_11');
$right_sth = $slave_dbh->prepare('SELECT * FROM test.issue_11');
$left_sth->execute();
$right_sth->execute();
$s = new MockSync();
$d->compare_sets(
left_sth => $left_sth,
right_sth => $right_sth,
syncer => $s,
tbl_struct => $tbl,
);
is_deeply(
$s,
[
['not in left', { a => 1, b => 2, c => 3 },],
'done',
],
'right only (real DBI sth)',
);
$slave_dbh->do('TRUNCATE TABLE test.issue_11');
$master_dbh->do('SET SQL_LOG_BIN=0;');
$master_dbh->do('INSERT INTO test.issue_11 VALUES (1,2,3)');
$left_sth = $master_dbh->prepare('SELECT * FROM test.issue_11');
$right_sth = $slave_dbh->prepare('SELECT * FROM test.issue_11');
$left_sth->execute();
$right_sth->execute();
$s = new MockSync();
$d->compare_sets(
left_sth => $left_sth,
right_sth => $right_sth,
syncer => $s,
tbl_struct => $tbl,
);
is_deeply(
$s,
[
[ 'not in right', { a => 1, b => 2, c => 3 },],
'done',
],
'left only (real DBI sth)',
);
$slave_dbh->do('INSERT INTO test.issue_11 VALUES (1,2,3)');
$left_sth = $master_dbh->prepare('SELECT * FROM test.issue_11');
$right_sth = $slave_dbh->prepare('SELECT * FROM test.issue_11');
$left_sth->execute();
$right_sth->execute();
$s = new MockSync();
$d->compare_sets(
left_sth => $left_sth,
right_sth => $right_sth,
syncer => $s,
tbl_struct => $tbl,
);
is_deeply(
$s,
[
'same',
'done',
],
'one identical row (real DBI sth)',
);
}
}
$sb->wipe_clean($master_dbh);
$sb->wipe_clean($slave_dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;