#!/usr/bin/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 Quoter; use QueryParser; use ReportFormatter; use Transformers; use DSNParser; use Sandbox; use CompareWarnings; use PerconaTest; my $dp = new DSNParser(opts=>$dsn_opts); my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); my $dbh = $sb->get_dbh_for('master', {no_lc=>1}); if ( !$dbh ) { plan skip_all => "Cannot connect to sandbox master"; } elsif ($sandbox_version ge '5.7') { plan skip_all => "MySQL 5.7 use a more strict sql_mode"; } else { plan tests => 21; } $sb->create_dbs($dbh, ['test']); Transformers->import(qw(make_checksum)); my $q = new Quoter(); my $qp = new QueryParser(); my %modules = ( Quoter => $q, QueryParser => $qp, ); my $cw; my $report; my @events; my $hosts = [ { dbh => $dbh, name => 'dbh-1' }, { dbh => $dbh, name => 'dbh-2' }, ]; sub proc { my ( $when, %args ) = @_; die "I don't know when $when is" unless $when eq 'before_execute' || $when eq 'execute' || $when eq 'after_execute'; for my $i ( 0..$#events ) { $events[$i] = $cw->$when( event => $events[$i], dbh => $hosts->[$i]->{dbh}, %args, ); } }; sub get_id { return make_checksum(@_); } # ############################################################################# # Test it. # ############################################################################# diag(`/tmp/12345/use < $trunk/t/lib/samples/compare-warnings.sql`); @events = ( { arg => 'select * from test.t', fingerprint => 'select * from test.t', sampleno => 1, }, { arg => 'select * from test.t', fingerprint => 'select * from test.t', sampleno => 1, }, ); $cw = new CompareWarnings( 'clear-warnings' => 1, 'clear-warnings-table' => 'mysql.bad', get_id => \&get_id, %modules, ); isa_ok($cw, 'CompareWarnings'); eval { $cw->before_execute( event => $events[0], dbh => $dbh, ); }; like( $EVAL_ERROR, qr/^Failed/, "Can't clear warnings with bad table" ); $cw = new CompareWarnings( 'clear-warnings' => 1, get_id => \&get_id, %modules, ); eval { $cw->before_execute( event => { arg => 'select * from bad.db' }, dbh => $dbh, ); }; like( $EVAL_ERROR, qr/^Failed/, "Can't clear warnings with query with bad tables" ); proc('before_execute', db=>'test'); $events[0]->{Query_time} = 123; proc('execute'); is( $events[0]->{Query_time}, 123, "execute() doesn't execute if Query_time already exists" ); ok( exists $events[1]->{Query_time} && $events[1]->{Query_time} >= 0, "execute() will execute if Query_time doesn't exist ($events[1]->{Query_time})" ); proc('after_execute'); is( $events[0]->{warning_count}, 0, 'Zero warning count' ); is_deeply( $events[0]->{warnings}, {}, 'No warnings' ); # ############################################################################# # Test with the same warning on both hosts. # ############################################################################# @events = ( { arg => "insert into test.t values (-2,'hi2',2)", fingerprint => 'insert into test.t values (?,?,?)', sampleno => 1, }, { arg => "insert into test.t values (-2,'hi2',2)", fingerprint => 'insert into test.t values (?,?,?)', sampleno => 1, }, ); proc('before_execute'); proc('execute'); proc('after_execute'); ok( $events[0]->{warning_count} == 1 && $events[1]->{warning_count} == 1, 'Both events had 1 warning' ); is_deeply( $events[0]->{warnings}, { '1264' => { Code => '1264', Level => 'Warning', Message => 'Out of range value for column \'i\' at row 1' } }, 'Event 0 has 1264 warning' ); is_deeply( $events[1]->{warnings}, { '1264' => { Code => '1264', Level => 'Warning', Message => 'Out of range value for column \'i\' at row 1' } }, 'Event 1 has same 1264 warning' ); # Compare the warnings: there should be no diffs since they're the same. is_deeply( [ $cw->compare(events => \@events, hosts => $hosts) ], [qw( different_warning_counts 0 different_warnings 0 different_warning_levels 0 )], 'compare(), no differences' ); ok( !exists $events[0]->{warnings} && !exists $events[1]->{warnings}, 'compare() deletes the warnings hashes from the events' ); # Add the warnings back with an increased level on the second event. my $w1 = { '1264' => { Code => '1264', Level => 'Warning', Message => 'Out of range value for column \'i\' at row 1' }, }; my $w2 = { '1264' => { Code => '1264', Level => 'Error', # diff Message => 'Out of range value for column \'i\' at row 1' }, }; %{$events[0]->{warnings}} = %{$w1}; %{$events[1]->{warnings}} = %{$w2}; is_deeply( [ $cw->compare(events => \@events, hosts => $hosts) ], [qw( different_warning_counts 0 different_warnings 0 different_warning_levels 1 )], 'compare(), same warnings but different levels' ); $report = <report(hosts => $hosts), $report, 'report warning level difference' ); $w2->{1264}->{Level} = 'Warning'; $cw->reset(); # Make like the warning didn't happen on the 2nd event. %{$events[0]->{warnings}} = %{$w1}; $events[0]->{warning_count} = 1; delete $events[1]->{warnings}; $events[1]->{warning_count} = 0; is_deeply( [ $cw->compare(events => \@events, hosts => $hosts) ], [qw( different_warning_counts 1 different_warnings 1 different_warning_levels 0 )], 'compare(), warning only on event 0' ); $report = <report(hosts => $hosts), $report, 'report new warning on host 1' ); # Make like the warning didn't happen on the first event; delete $events[0]->{warnings}; $events[0]->{warning_count} = 0; %{$events[1]->{warnings}} = %{$w2}; $events[1]->{warning_count} = 1; is_deeply( [ $cw->compare(events => \@events, hosts => $hosts) ], [qw( different_warning_counts 1 different_warnings 1 different_warning_levels 0 )], 'compare(), warning only on event 1' ); $report = <report(hosts => $hosts), $report, 'report new warning on host 2' ); is_deeply( [ $cw->samples('insert into test.t values (?,?,?)') ], [ '1', "insert into test.t values (-2,'hi2',2)" ], 'samples()' ); # ############################################################################# # Done. # ############################################################################# my $output = ''; { local *STDERR; open STDERR, '>', \$output; $cw->_d('Complete test coverage'); } like( $output, qr/Complete test coverage/, '_d() works' ); $sb->wipe_clean($dbh); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); exit;