mtr_report.pl 15.4 KB
Newer Older
unknown's avatar
unknown committed
1
# -*- cperl -*-
unknown's avatar
unknown committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15
# Copyright (C) 2004-2006 MySQL AB
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
unknown's avatar
unknown committed
16 17 18 19 20 21

# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.

use strict;
22
use warnings;
unknown's avatar
unknown committed
23 24 25 26 27

sub mtr_report_test_name($);
sub mtr_report_test_passed($);
sub mtr_report_test_failed($);
sub mtr_report_test_skipped($);
unknown's avatar
unknown committed
28
sub mtr_report_test_not_skipped_though_disabled($);
unknown's avatar
unknown committed
29 30 31

sub mtr_report_stats ($);
sub mtr_print_line ();
unknown's avatar
unknown committed
32
sub mtr_print_thick_line ();
unknown's avatar
unknown committed
33 34 35 36
sub mtr_print_header ();
sub mtr_report (@);
sub mtr_warning (@);
sub mtr_error (@);
37
sub mtr_child_error (@);
unknown's avatar
unknown committed
38
sub mtr_debug (@);
unknown's avatar
unknown committed
39
sub mtr_verbose (@);
unknown's avatar
unknown committed
40

41 42 43
my $tot_real_time= 0;


unknown's avatar
unknown committed
44 45 46 47 48 49 50 51 52 53

##############################################################################
#
#  
#
##############################################################################

sub mtr_report_test_name ($) {
  my $tinfo= shift;

54
  _mtr_log("$tinfo->{name}");
55
  printf "%-30s ", $tinfo->{'name'};
unknown's avatar
unknown committed
56 57 58 59 60 61
}

sub mtr_report_test_skipped ($) {
  my $tinfo= shift;

  $tinfo->{'result'}= 'MTR_RES_SKIPPED';
unknown's avatar
unknown committed
62 63
  if ( $tinfo->{'disable'} )
  {
64
    mtr_report("[ disabled ]  $tinfo->{'comment'}");
unknown's avatar
unknown committed
65
  }
unknown's avatar
unknown committed
66
  elsif ( $tinfo->{'comment'} )
unknown's avatar
unknown committed
67
  {
68
    mtr_report("[ skipped ]   $tinfo->{'comment'}");
unknown's avatar
unknown committed
69
  }
unknown's avatar
unknown committed
70 71
  else
  {
72
    mtr_report("[ skipped ]");
unknown's avatar
unknown committed
73
  }
unknown's avatar
unknown committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
}

sub mtr_report_tests_not_skipped_though_disabled ($) {
  my $tests= shift;

  if ( $::opt_enable_disabled )
  {
    my @disabled_tests= grep {$_->{'dont_skip_though_disabled'}} @$tests;
    if ( @disabled_tests )
    {
      print "\nTest(s) which will be run though they are marked as disabled:\n";
      foreach my $tinfo ( sort {$a->{'name'} cmp $b->{'name'}} @disabled_tests )
      {
        printf "  %-20s : %s\n", $tinfo->{'name'}, $tinfo->{'comment'};
      }
    }
unknown's avatar
unknown committed
90
  }
unknown's avatar
unknown committed
91 92 93 94 95 96
}

sub mtr_report_test_passed ($) {
  my $tinfo= shift;

  my $timer=  "";
97
  if ( $::opt_timer and -f "$::opt_vardir/log/timer" )
unknown's avatar
unknown committed
98
  {
99
    $timer= mtr_fromfile("$::opt_vardir/log/timer");
100
    $tot_real_time += ($timer/1000);
unknown's avatar
unknown committed
101 102
    $timer= sprintf "%12s", $timer;
  }
unknown's avatar
unknown committed
103
  $tinfo->{'result'}= 'MTR_RES_PASSED';
104
  mtr_report("[ pass ]   $timer");
unknown's avatar
unknown committed
105 106 107 108 109 110
}

sub mtr_report_test_failed ($) {
  my $tinfo= shift;

  $tinfo->{'result'}= 'MTR_RES_FAILED';
unknown's avatar
unknown committed
111
  if ( defined $tinfo->{'timeout'} )
112
  {
113
    mtr_report("[ fail ]  timeout");
114
    return;
115 116 117
  }
  else
  {
118
    mtr_report("[ fail ]");
119
  }
unknown's avatar
unknown committed
120

121 122
  if ( $tinfo->{'comment'} )
  {
123 124 125
    # The test failure has been detected by mysql-test-run.pl
    # when starting the servers or due to other error, the reason for
    # failing the test is saved in "comment"
126
    mtr_report("\nERROR: $tinfo->{'comment'}");
127 128
  }
  elsif ( -f $::path_timefile )
unknown's avatar
unknown committed
129
  {
130 131 132
    # Test failure was detected by test tool and it's report
    # about what failed has been saved to file. Display the report.
    print "\n";
unknown's avatar
unknown committed
133
    print mtr_fromfile($::path_timefile); # FIXME print_file() instead
134
    print "\n";
unknown's avatar
unknown committed
135 136 137
  }
  else
  {
138 139
    # Neither this script or the test tool has recorded info
    # about why the test has failed. Should be debugged.
140
    mtr_report("\nUnexpected termination, probably when starting mysqld");;
unknown's avatar
unknown committed
141
  }
unknown's avatar
unknown committed
142 143 144 145 146 147 148 149 150 151 152 153 154
}

sub mtr_report_stats ($) {
  my $tests= shift;

  # ----------------------------------------------------------------------
  # Find out how we where doing
  # ----------------------------------------------------------------------

  my $tot_skiped= 0;
  my $tot_passed= 0;
  my $tot_failed= 0;
  my $tot_tests=  0;
unknown's avatar
unknown committed
155
  my $tot_restarts= 0;
156
  my $found_problems= 0; # Some warnings in the logfiles are errors...
unknown's avatar
unknown committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

  foreach my $tinfo (@$tests)
  {
    if ( $tinfo->{'result'} eq 'MTR_RES_SKIPPED' )
    {
      $tot_skiped++;
    }
    elsif ( $tinfo->{'result'} eq 'MTR_RES_PASSED' )
    {
      $tot_tests++;
      $tot_passed++;
    }
    elsif ( $tinfo->{'result'} eq 'MTR_RES_FAILED' )
    {
      $tot_tests++;
      $tot_failed++;
    }
unknown's avatar
unknown committed
174 175 176 177
    if ( $tinfo->{'restarted'} )
    {
      $tot_restarts++;
    }
unknown's avatar
unknown committed
178 179 180 181 182 183 184 185 186 187 188 189 190
  }

  # ----------------------------------------------------------------------
  # Print out a summary report to screen
  # ----------------------------------------------------------------------

  if ( ! $tot_failed )
  {
    print "All $tot_tests tests were successful.\n";
  }
  else
  {
    my $ratio=  $tot_passed * 100 / $tot_tests;
191 192 193
    print "Failed $tot_failed/$tot_tests tests, ";
    printf("%.2f", $ratio);
    print "\% were successful.\n\n";
unknown's avatar
unknown committed
194 195
    print
      "The log files in var/log may give you some hint\n",
196
      "of what went wrong.\n",
unknown's avatar
unknown committed
197 198
      "If you want to report this error, please read first ",
      "the documentation at\n",
unknown's avatar
unknown committed
199
      "http://dev.mysql.com/doc/mysql/en/mysql-test-suite.html\n";
unknown's avatar
unknown committed
200
  }
unknown's avatar
unknown committed
201 202
  if (!$::opt_extern)
  {
unknown's avatar
unknown committed
203
    print "The servers were restarted $tot_restarts times\n";
unknown's avatar
unknown committed
204
  }
unknown's avatar
unknown committed
205 206 207

  if ( $::opt_timer )
  {
208 209 210 211
    use English;

    mtr_report("Spent", sprintf("%.3f", $tot_real_time),"of",
	       time - $BASETIME, "seconds executing testcases");
unknown's avatar
unknown committed
212
  }
unknown's avatar
unknown committed
213 214

  # ----------------------------------------------------------------------
unknown's avatar
unknown committed
215 216
  # If a debug run, there might be interesting information inside
  # the "var/log/*.err" files. We save this info in "var/log/warnings"
unknown's avatar
unknown committed
217 218 219 220
  # ----------------------------------------------------------------------

  if ( ! $::glob_use_running_server )
  {
unknown's avatar
unknown committed
221
    # Save and report if there was any fatal warnings/errors in err logs
unknown's avatar
unknown committed
222

unknown's avatar
unknown committed
223 224 225 226 227 228 229 230 231
    my $warnlog= "$::opt_vardir/log/warnings";

    unless ( open(WARN, ">$warnlog") )
    {
      mtr_warning("can't write to the file \"$warnlog\": $!");
    }
    else
    {
      # We report different types of problems in order
232 233 234 235 236
      foreach my $pattern ( "^Warning:",
			    "\\[Warning\\]",
			    "\\[ERROR\\]",
			    "^Error:", "^==.* at 0x",
			    "InnoDB: Warning",
unknown's avatar
unknown committed
237
			    "InnoDB: Error",
238 239
			    "^safe_mutex:",
			    "missing DBUG_RETURN",
unknown's avatar
unknown committed
240
			    "mysqld: Warning",
241
			    "allocated at line",
unknown's avatar
unknown committed
242 243 244 245
			    "Attempting backtrace", "Assertion .* failed" )
      {
        foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") )
        {
246
	  my $testname= "";
unknown's avatar
unknown committed
247 248 249 250 251
          unless ( open(ERR, $errlog) )
          {
            mtr_warning("can't read $errlog");
            next;
          }
252
          my $leak_reports_expected= undef;
unknown's avatar
unknown committed
253 254
          while ( <ERR> )
          {
255 256 257 258 259 260 261 262 263 264
            # There is a test case that purposely provokes a
            # SAFEMALLOC leak report, even though there is no actual
            # leak. We need to detect this, and ignore the warning in
            # that case.
            if (/Begin safemalloc memory dump:/) {
              $leak_reports_expected= 1;
            } elsif (/End safemalloc memory dump./) {
              $leak_reports_expected= undef;
            }

unknown's avatar
unknown committed
265
            # Skip some non fatal warnings from the log files
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
            if (
		/\"SELECT UNIX_TIMESTAMP\(\)\" failed on master/ or
		/Aborted connection/ or
		/Client requested master to start replication from impossible position/ or
		/Could not find first log file name in binary log/ or
		/Enabling keys got errno/ or
		/Error reading master configuration/ or
		/Error reading packet/ or
		/Event Scheduler/ or
		/Failed to open log/ or
		/Failed to open the existing master info file/ or
		/Forcing shutdown of [0-9]* plugins/ or
		/Got error [0-9]* when reading table/ or
		/Incorrect definition of table/ or
		/Incorrect information in file/ or
		/InnoDB: Warning: we did not need to do crash recovery/ or
		/Invalid \(old\?\) table or database name/ or
		/Lock wait timeout exceeded/ or
		/Log entry on master is longer than max_allowed_packet/ or
                /unknown option '--loose-/ or
                /unknown variable 'loose-/ or
		/You have forced lower_case_table_names to 0 through a command-line option/ or
		/Setting lower_case_table_names=2/ or
		/NDB Binlog:/ or
		/NDB: failed to setup table/ or
		/NDB: only row based binary logging/ or
		/Neither --relay-log nor --relay-log-index were used/ or
		/Query partially completed/ or
		/Slave I.O thread aborted while waiting for relay log/ or
		/Slave SQL thread is stopped because UNTIL condition/ or
		/Slave SQL thread retried transaction/ or
		/Slave \(additional info\)/ or
		/Slave: .*Duplicate column name/ or
		/Slave: .*master may suffer from/ or
		/Slave: According to the master's version/ or
		/Slave: Column [0-9]* type mismatch/ or
		/Slave: Error .* doesn't exist/ or
		/Slave: Error .*Deadlock found/ or
		/Slave: Error .*Unknown table/ or
		/Slave: Error in Write_rows event: / or
		/Slave: Field .* of table .* has no default value/ or
		/Slave: Query caused different errors on master and slave/ or
		/Slave: Table .* doesn't exist/ or
		/Slave: Table width mismatch/ or
		/Slave: The incident LOST_EVENTS occured on the master/ or
		/Slave: Unknown error.* 1105/ or
		/Slave: Can't drop database.* database doesn't exist/ or
313
                /Slave SQL:.*(?:Error_code: \d+|Query:.*)/ or
314 315 316 317 318 319 320 321 322 323 324 325 326 327
		/Sort aborted/ or
		/Time-out in NDB/ or
		/Warning:\s+One can only use the --user.*root/ or
		/Warning:\s+Setting lower_case_table_names=2/ or
		/Warning:\s+Table:.* on (delete|rename)/ or
		/You have an error in your SQL syntax/ or
		/deprecated/ or
		/description of time zone/ or
		/equal MySQL server ids/ or
		/error .*connecting to master/ or
		/error reading log entry/ or
		/lower_case_table_names is set/ or
		/skip-name-resolve mode/ or
		/slave SQL thread aborted/ or
unknown's avatar
unknown committed
328
		/Slave: .*Duplicate entry/ or
unknown's avatar
unknown committed
329 330 331 332
		# Special case for Bug #26402 in show_check.test
		# Question marks are not valid file name parts
		# on Windows platforms. Ignore this error message. 
		/\QCan't find file: '.\test\????????.frm'\E/ or
unknown's avatar
unknown committed
333 334 335
		# Special case, made as specific as possible, for:
		# Bug #28436: Incorrect position in SHOW BINLOG EVENTS causes
		#             server coredump
336
		/\QError in Log_event::read_log_event(): 'Sanity check failed', data_len: 258, event_type: 49\E/ or
unknown's avatar
unknown committed
337 338
                /Statement is not safe to log in statement format/ or

unknown's avatar
unknown committed
339 340
                # test case for Bug#bug29807 copies a stray frm into database
                /InnoDB: Error: table `test`.`bug29807` does not exist in the InnoDB internal/ or
341
                /Cannot find or open table test\/bug29807 from/ or
unknown's avatar
unknown committed
342 343 344 345 346 347

                # innodb foreign key tests that fail in ALTER or RENAME produce this
                /InnoDB: Error: in ALTER TABLE `test`.`t[12]`/ or
                /InnoDB: Error: in RENAME TABLE table `test`.`t1`/ or
                /InnoDB: Error: table `test`.`t[12]` does not exist in the InnoDB internal/ or

unknown's avatar
unknown committed
348 349 350
                # Test case for Bug#14233 produces the following warnings:
                /Stored routine 'test'.'bug14233_1': invalid value in column mysql.proc/ or
                /Stored routine 'test'.'bug14233_2': invalid value in column mysql.proc/ or
351 352
                /Stored routine 'test'.'bug14233_3': invalid value in column mysql.proc/ or

353 354
                # BUG#29839 - lowercase_table3.test: Cannot find table test/T1
                #             from the internal data dictiona
355 356 357 358 359 360 361 362 363
                /Cannot find table test\/BUG29839 from the internal data dictionary/ or

		# rpl_extrColmaster_*.test, the slave thread produces warnings
		# when it get updates to a table that has more columns on the
		# master
		/Slave: Unknown column 'c7' in 't15' Error_code: 1054/ or
		/Slave: Can't DROP 'c7'.* 1091/ or
		/Slave: Key column 'c6'.* 1072/

364
	       )
unknown's avatar
unknown committed
365 366 367
            {
              next;                       # Skip these lines
            }
368 369 370 371
	    if ( /CURRENT_TEST: (.*)/ )
	    {
	      $testname= $1;
	    }
unknown's avatar
unknown committed
372 373
            if ( /$pattern/ )
            {
374 375 376
              if ($leak_reports_expected) {
                next;
              }
unknown's avatar
unknown committed
377
              $found_problems= 1;
378
              print WARN basename($errlog) . ": $testname: $_";
unknown's avatar
unknown committed
379 380 381 382
            }
          }
        }
      }
383

384
      if ( $::opt_check_testcases )
385
      {
386 387 388 389 390 391 392
        # Look for warnings produced by mysqltest in testname.warnings
        foreach my $test_warning_file
	  ( glob("$::glob_mysql_test_dir/r/*.warnings") )
        {
          $found_problems= 1;
	  print WARN "Check myqltest warnings in $test_warning_file\n";
        }
393 394
      }

unknown's avatar
unknown committed
395 396 397 398 399 400
      if ( $found_problems )
      {
	mtr_warning("Got errors/warnings while running tests, please examine",
		    "\"$warnlog\" for details.");
      }
    }
unknown's avatar
unknown committed
401 402 403 404
  }

  print "\n";

405
  # Print a list of testcases that failed
unknown's avatar
unknown committed
406 407
  if ( $tot_failed != 0 )
  {
408 409
    my $test_mode= join(" ", @::glob_test_mode) || "default";
    print "mysql-test-run in $test_mode mode: *** Failing the test(s):";
unknown's avatar
unknown committed
410 411 412 413 414 415 416 417 418

    foreach my $tinfo (@$tests)
    {
      if ( $tinfo->{'result'} eq 'MTR_RES_FAILED' )
      {
        print " $tinfo->{'name'}";
      }
    }
    print "\n";
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440

  }

  # Print a list of check_testcases that failed(if any)
  if ( $::opt_check_testcases )
  {
    my @check_testcases= ();

    foreach my $tinfo (@$tests)
    {
      if ( defined $tinfo->{'check_testcase_failed'} )
      {
	push(@check_testcases, $tinfo->{'name'});
      }
    }

    if ( @check_testcases )
    {
      print "Check of testcase failed for: ";
      print join(" ", @check_testcases);
      print "\n\n";
    }
unknown's avatar
unknown committed
441
  }
442

unknown's avatar
unknown committed
443 444
  if ( $tot_failed != 0 || $found_problems)
  {
unknown's avatar
unknown committed
445
    mtr_error("there were failing test cases");
unknown's avatar
unknown committed
446 447 448 449 450 451 452 453 454 455 456 457 458
  }
}

##############################################################################
#
#  Text formatting
#
##############################################################################

sub mtr_print_line () {
  print '-' x 55, "\n";
}

unknown's avatar
unknown committed
459 460 461 462
sub mtr_print_thick_line () {
  print '=' x 55, "\n";
}

unknown's avatar
unknown committed
463 464 465 466
sub mtr_print_header () {
  print "\n";
  if ( $::opt_timer )
  {
unknown's avatar
unknown committed
467
    print "TEST                           RESULT         TIME (ms)\n";
unknown's avatar
unknown committed
468 469 470
  }
  else
  {
unknown's avatar
unknown committed
471
    print "TEST                           RESULT\n";
unknown's avatar
unknown committed
472 473 474 475 476 477 478 479
  }
  mtr_print_line();
  print "\n";
}


##############################################################################
#
480
#  Log and reporting functions
unknown's avatar
unknown committed
481 482 483
#
##############################################################################

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
use IO::File;

my $log_file_ref= undef;

sub mtr_log_init ($) {
  my ($filename)= @_;

  mtr_error("Log is already open") if defined $log_file_ref;

  $log_file_ref= IO::File->new($filename, "a") or
    mtr_warning("Could not create logfile $filename: $!");
}

sub _mtr_log (@) {
  print $log_file_ref join(" ", @_),"\n"
    if defined $log_file_ref;
}

unknown's avatar
unknown committed
502
sub mtr_report (@) {
503 504
  # Print message to screen and log
  _mtr_log(@_);
unknown's avatar
unknown committed
505 506 507 508
  print join(" ", @_),"\n";
}

sub mtr_warning (@) {
509 510
  # Print message to screen and log
  _mtr_log("WARNING: ", @_);
unknown's avatar
unknown committed
511 512 513 514
  print STDERR "mysql-test-run: WARNING: ",join(" ", @_),"\n";
}

sub mtr_error (@) {
515 516
  # Print message to screen and log
  _mtr_log("ERROR: ", @_);
unknown's avatar
unknown committed
517 518
  print STDERR "mysql-test-run: *** ERROR: ",join(" ", @_),"\n";
  mtr_exit(1);
unknown's avatar
unknown committed
519 520
}

521
sub mtr_child_error (@) {
522 523
  # Print message to screen and log
  _mtr_log("ERROR(child): ", @_);
524 525 526 527
  print STDERR "mysql-test-run: *** ERROR(child): ",join(" ", @_),"\n";
  exit(1);
}

unknown's avatar
unknown committed
528
sub mtr_debug (@) {
529
  # Only print if --script-debug is used
unknown's avatar
unknown committed
530 531
  if ( $::opt_script_debug )
  {
532
    _mtr_log("###: ", @_);
unknown's avatar
unknown committed
533
    print STDERR "####: ",join(" ", @_),"\n";
unknown's avatar
unknown committed
534 535
  }
}
536

unknown's avatar
unknown committed
537
sub mtr_verbose (@) {
538 539
  # Always print to log, print to screen only when --verbose is used
  _mtr_log("> ",@_);
unknown's avatar
unknown committed
540 541 542 543 544
  if ( $::opt_verbose )
  {
    print STDERR "> ",join(" ", @_),"\n";
  }
}
unknown's avatar
unknown committed
545 546

1;