1#!/usr/bin/perl 2# -*- cperl -*- 3 4# Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License, version 2.0, 8# as published by the Free Software Foundation. 9# 10# This program is also distributed with certain software (including 11# but not limited to OpenSSL) that is licensed under separate terms, 12# as designated in a particular file or component or in included license 13# documentation. The authors of MySQL hereby grant you an additional 14# permission to link the program and your derivative works with the 15# separately licensed software that they have included with MySQL. 16# 17# This program is distributed in the hope that it will be useful, 18# but WITHOUT ANY WARRANTY; without even the implied warranty of 19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20# GNU General Public License, version 2.0, for more details. 21# 22# You should have received a copy of the GNU General Public License 23# along with this program; if not, write to the Free Software 24# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 26# 27############################################################################## 28# 29# mysql-test-run.pl 30# 31# Tool used for executing a suite of .test files 32# 33# See the "MySQL Test framework manual" for more information 34# http://dev.mysql.com/doc/mysqltest/en/index.html 35# 36# 37############################################################################## 38 39use strict; 40use warnings; 41 42BEGIN { 43 # Check that mysql-test-run.pl is started from mysql-test/ 44 unless ( -f "mysql-test-run.pl" ) 45 { 46 print "**** ERROR **** ", 47 "You must start mysql-test-run from the mysql-test/ directory\n"; 48 exit(1); 49 } 50 # Check that lib exist 51 unless ( -d "lib/" ) 52 { 53 print "**** ERROR **** ", 54 "Could not find the lib/ directory \n"; 55 exit(1); 56 } 57} 58 59BEGIN { 60 # Check backward compatibility support 61 # By setting the environment variable MTR_VERSION 62 # it's possible to use a previous version of 63 # mysql-test-run.pl 64 my $version= $ENV{MTR_VERSION} || 2; 65 if ( $version == 1 ) 66 { 67 print "=======================================================\n"; 68 print " WARNING: Using mysql-test-run.pl version 1! \n"; 69 print "=======================================================\n"; 70 # Should use exec() here on *nix but this appears not to work on Windows 71 exit(system($^X, "lib/v1/mysql-test-run.pl", @ARGV) >> 8); 72 } 73 elsif ( $version == 2 ) 74 { 75 # This is the current version, just continue 76 ; 77 } 78 else 79 { 80 print "ERROR: Version $version of mysql-test-run does not exist!\n"; 81 exit(1); 82 } 83} 84 85use lib "lib"; 86 87use Cwd; 88use Cwd "abs_path"; 89use Getopt::Long; 90use My::File::Path; # Patched version of File::Path 91use File::Basename; 92use File::Copy; 93use File::Find; 94use File::Temp qw/tempdir/; 95use File::Spec::Functions qw/splitdir/; 96use My::Constants; 97use My::Platform; 98use My::SafeProcess; 99use My::ConfigFactory; 100use My::Options; 101use My::Find; 102use My::SysInfo; 103use My::CoreDump; 104use mtr_cases; 105use mtr_report; 106use mtr_report_junit; 107use mtr_match; 108use mtr_unique; 109use mtr_results; 110use IO::Socket::INET; 111use IO::Select; 112use Subunit; 113 114push @INC, "."; 115 116require "lib/mtr_process.pl"; 117require "lib/mtr_io.pl"; 118require "lib/mtr_gcov.pl"; 119require "lib/mtr_gprof.pl"; 120require "lib/mtr_misc.pl"; 121 122$SIG{INT}= sub { mtr_error("Got ^C signal"); }; 123 124our $mysql_version_id; 125my $mysql_version_extra; 126our $glob_mysql_test_dir; 127our $basedir; 128our $bindir; 129 130our $path_charsetsdir; 131our $path_client_bindir; 132our $path_client_libdir; 133our $path_language; 134 135our $path_current_testlog; 136our $path_testlog; 137 138our $default_vardir; 139our $opt_vardir; # Path to use for var/ dir 140my $path_vardir_trace; # unix formatted opt_vardir for trace files 141my $opt_tmpdir; # Path to use for tmp/ dir 142my $opt_tmpdir_pid; 143 144my $opt_start; 145my $opt_start_dirty; 146my $opt_start_exit; 147my $start_only; 148 149my $auth_plugin; # the path to the authentication test plugin 150 151END { 152 if ( defined $opt_tmpdir_pid and $opt_tmpdir_pid == $$ ) 153 { 154 if (!$opt_start_exit) 155 { 156 # Remove the tempdir this process has created 157 mtr_verbose("Removing tmpdir $opt_tmpdir"); 158 rmtree($opt_tmpdir); 159 } 160 else 161 { 162 mtr_warning("tmpdir $opt_tmpdir should be removed after the server has finished"); 163 } 164 } 165} 166 167sub env_or_val($$) { defined $ENV{$_[0]} ? $ENV{$_[0]} : $_[1] } 168 169# set_term_args(user_specified_string, term_exe_variable, term_args_arr, title) 170sub set_term_args { 171 my $term_cmd = $_[0]; 172 if ($term_cmd =~ /^ *$/) { 173 mtr_error("MTR_TERM is defined, but empty"); 174 } 175 my @term_args = split / /, $term_cmd; 176 $_[1] = shift @term_args; 177 foreach my $t_arg (@term_args) { 178 if ($t_arg eq "%title%") { 179 mtr_add_arg($_[2], "$_[3]"); 180 } else { 181 mtr_add_arg($_[2], $t_arg); 182 } 183 } 184 185} 186 187my $path_config_file; # The generated config file, var/my.cnf 188 189# Visual Studio produces executables in different sub-directories based on the 190# configuration used to build them. To make life easier, an environment 191# variable or command-line option may be specified to control which set of 192# executables will be used by the test suite. 193our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; 194 195# If you add a new suite, please check TEST_DIRS in Makefile.am. 196# 197my $DEFAULT_SUITES= "main,sys_vars,binlog,federated,rpl,innodb,innodb_fts," 198 ."innodb_zip,perfschema,funcs_1,funcs_2,opt_trace,parts,auth_sec," 199 ."connection_control,jp,stress,engines/iuds,engines/funcs," 200 ."query_response_time,innodb_stress,tokudb.add_index,tokudb.alter_table," 201 ."tokudb,tokudb.bugs,tokudb.parts,tokudb.rpl,tokudb.perfschema," 202 ."percona-pam-for-mysql"; 203my $opt_suites; 204 205our $opt_verbose= 0; # Verbose output, enable with --verbose 206our $exe_mysql; 207our $exe_mysql_plugin; 208our $exe_mysqladmin; 209our $exe_mysqltest; 210our $exe_libtool; 211our $exe_mysql_embedded; 212 213our $opt_big_test= 0; 214 215our @opt_combinations; 216 217our @opt_extra_mysqld_opt; 218our @opt_mysqld_envs; 219 220my $opt_stress; 221 222my $opt_compress; 223my $opt_ssl; 224my $opt_skip_ssl; 225my @opt_skip_test_list; 226our $opt_ssl_supported; 227my $opt_ps_protocol; 228my $opt_sp_protocol; 229my $opt_cursor_protocol; 230my $opt_view_protocol; 231my $opt_trace_protocol; 232my $opt_explain_protocol; 233my $opt_json_explain_protocol; 234 235our $opt_debug; 236my $debug_d= "d"; 237my $opt_debug_common; 238our $opt_debug_server; 239our @opt_cases; # The test cases names in argv 240our $opt_embedded_server; 241# -1 indicates use default, override with env.var. 242our $opt_ctest= env_or_val(MTR_UNIT_TESTS => -1); 243our $opt_ctest_report; 244# Unit test report stored here for delayed printing 245my $ctest_report; 246 247# Options used when connecting to an already running server 248my %opts_extern; 249sub using_extern { return (keys %opts_extern > 0);}; 250 251our $opt_fast= 0; 252our $opt_force; 253our $opt_mem= $ENV{'MTR_MEM'}; 254our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'}; 255 256our $opt_gcov; 257our $opt_gcov_exe= "gcov"; 258our $opt_gcov_err= "mysql-test-gcov.err"; 259our $opt_gcov_msg= "mysql-test-gcov.msg"; 260 261our $opt_gprof; 262our %gprof_dirs; 263 264our $glob_debugger= 0; 265our $opt_gdb; 266our $opt_client_gdb; 267my $opt_boot_gdb; 268our $opt_lldb; 269our $opt_dbx; 270our $opt_client_dbx; 271my $opt_boot_dbx; 272our $opt_ddd; 273our $opt_client_ddd; 274my $opt_boot_ddd; 275our $opt_manual_gdb; 276our $opt_manual_lldb; 277our $opt_manual_dbx; 278our $opt_manual_ddd; 279our $opt_manual_debug; 280our $opt_debugger; 281our $opt_client_debugger; 282 283my $config; # The currently running config 284my $current_config_name; # The currently running config file template 285 286our @opt_experimentals; 287our $experimental_test_cases= []; 288 289my $baseport; 290# $opt_build_thread may later be set from $opt_port_base 291my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto"; 292my $opt_port_base= $ENV{'MTR_PORT_BASE'} || "auto"; 293my $build_thread= 0; 294 295my $opt_record; 296my $opt_report_features; 297 298our $opt_resfile= $ENV{'MTR_RESULT_FILE'} || 0; 299 300my $opt_skip_core; 301 302our $opt_check_testcases= 1; 303my $opt_mark_progress; 304my $opt_max_connections; 305our $opt_report_times= 0; 306 307my $opt_sleep; 308 309my $opt_testcase_timeout= $ENV{MTR_TESTCASE_TIMEOUT} || 15; # minutes 310my $opt_suite_timeout = $ENV{MTR_SUITE_TIMEOUT} || 300; # minutes 311my $opt_shutdown_timeout= $ENV{MTR_SHUTDOWN_TIMEOUT} || 20; # seconds 312my $opt_start_timeout = $ENV{MTR_START_TIMEOUT} || 180; # seconds 313 314sub suite_timeout { return $opt_suite_timeout * 60; }; 315 316my $opt_wait_all; 317my $opt_user_args; 318my $opt_repeat= 1; 319my $opt_retry= 3; 320my $opt_retry_failure= env_or_val(MTR_RETRY_FAILURE => 2); 321my $opt_reorder= 1; 322my $opt_force_restart= 0; 323 324my $opt_strace_client; 325my $opt_strace_server; 326 327our $opt_user = "root"; 328 329our $opt_valgrind= 0; 330my $shutdown_report= 0; 331my $shutdown_report_text= ''; 332my $opt_valgrind_mysqld= 0; 333my $opt_valgrind_mysqltest= 0; 334my @valgrind_args; 335my $opt_valgrind_path; 336my $opt_callgrind; 337my $opt_helgrind; 338my %mysqld_logs; 339my $opt_debug_sync_timeout= 600; # Default timeout for WAIT_FOR actions. 340my $opt_mtr_term_args = env_or_val(MTR_TERM => "xterm -title %title% -e"); 341my $opt_lldb_cmd = env_or_val(MTR_LLDB => "lldb"); 342 343sub testcase_timeout ($) { 344 my ($tinfo)= @_; 345 if (exists $tinfo->{'case-timeout'}) { 346 # Return test specific timeout if *longer* that the general timeout 347 my $test_to= $tinfo->{'case-timeout'}; 348 $test_to*= 10 if $opt_valgrind; 349 return $test_to * 60 if $test_to > $opt_testcase_timeout; 350 } 351 return $opt_testcase_timeout * 60; 352} 353 354sub check_timeout ($) { return testcase_timeout($_[0]) / 10; } 355 356our $opt_warnings= 1; 357 358our $ndbcluster_enabled= 0; 359my $opt_include_ndbcluster= 0; 360my $opt_skip_ndbcluster= 0; 361 362our $opt_junit_output= undef; 363our $opt_junit_package= undef; 364 365my $exe_ndbd; 366my $exe_ndbmtd; 367my $exe_ndb_mgmd; 368my $exe_ndb_waiter; 369my $exe_ndb_mgm; 370 371our $debug_compiled_binaries; 372 373our %mysqld_variables; 374 375my $source_dist= 0; 376 377my $opt_max_save_core= env_or_val(MTR_MAX_SAVE_CORE => 5); 378my $opt_max_save_datadir= env_or_val(MTR_MAX_SAVE_DATADIR => 20); 379my $opt_max_test_fail= env_or_val(MTR_MAX_TEST_FAIL => 10); 380 381my $opt_parallel= $ENV{MTR_PARALLEL} || 1; 382 383select(STDOUT); 384$| = 1; # Automatically flush STDOUT 385 386main(); 387 388sub is_core_dump { 389 my $core_name= shift; 390 # Name beginning with core, not ending in .gz, .c, nor .log, or ending with 391 # .dmp on Windows 392 return (($core_name =~ /^core/ and $core_name !~ /\.gz$|\.c$|\.log$/) 393 or (IS_WINDOWS and $core_name =~ /\.dmp$/)); 394} 395 396sub main { 397 # Default, verbosity on 398 report_option('verbose', 0); 399 400 # This is needed for test log evaluation in "gen-build-status-page" 401 # in all cases where the calling tool does not log the commands 402 # directly before it executes them, like "make test-force-pl" in RPM builds. 403 mtr_report("Logging: $0 ", join(" ", @ARGV)); 404 405 command_line_setup(); 406 407 # --help will not reach here, so now it's safe to assume we have binaries 408 My::SafeProcess::find_bin(); 409 410 if ( $opt_gcov ) { 411 gcov_prepare($basedir); 412 } 413 414 if (!$opt_suites) { 415 $opt_suites= $DEFAULT_SUITES; 416 } 417 mtr_report("Using suites: $opt_suites") unless @opt_cases; 418 419 init_timers(); 420 421 mtr_report("Collecting tests..."); 422 my $tests= collect_test_cases($opt_reorder, $opt_suites, \@opt_cases, \@opt_skip_test_list); 423 my $all_tests; 424 @$all_tests = @$tests; 425 mark_time_used('collect'); 426 427 if ( $opt_report_features ) { 428 # Put "report features" as the first test to run 429 my $tinfo = My::Test->new 430 ( 431 name => 'report_features', 432 # No result_file => Prints result 433 path => 'include/report-features.test', 434 template_path => "include/default_my.cnf", 435 master_opt => [], 436 slave_opt => [], 437 ); 438 unshift(@$tests, $tinfo); 439 } 440 441 initialize_servers(); 442 443 ####################################################################### 444 my $num_tests= @$tests; 445 if ( $opt_parallel eq "auto" ) { 446 # Try to find a suitable value for number of workers 447 my $sys_info= My::SysInfo->new(); 448 449 $opt_parallel= $sys_info->num_cpus(); 450 for my $limit (2000, 1500, 1000, 500){ 451 $opt_parallel-- if ($sys_info->min_bogomips() < $limit); 452 } 453 if(defined $ENV{MTR_MAX_PARALLEL}) { 454 my $max_par= $ENV{MTR_MAX_PARALLEL}; 455 $opt_parallel= $max_par if ($opt_parallel > $max_par); 456 } 457 $opt_parallel= 1 if ($opt_parallel < 1); 458 } 459 # Limit parallel workers to number of tests to avoid idle workers 460 $opt_parallel= $num_tests if ($num_tests > 0 and $opt_parallel > $num_tests); 461 $ENV{MTR_PARALLEL} = $opt_parallel; 462 mtr_report("Using parallel: $opt_parallel"); 463 464 if ($opt_parallel > 1 && ($opt_start_exit || $opt_stress)) { 465 mtr_warning("Parallel cannot be used with --start-and-exit or --stress\n" . 466 "Setting parallel to 1"); 467 $opt_parallel= 1; 468 } 469 470 # Create server socket on any free port 471 my $server = new IO::Socket::INET 472 ( 473 LocalAddr => 'localhost', 474 Proto => 'tcp', 475 Listen => $opt_parallel, 476 ); 477 mtr_error("Could not create testcase server port: $!") unless $server; 478 my $server_port = $server->sockport(); 479 480 if ($opt_resfile) { 481 resfile_init("$opt_vardir/mtr-results.txt"); 482 print_global_resfile(); 483 } 484 485 # -------------------------------------------------------------------------- 486 # Read definitions from include/plugin.defs 487 # 488 read_plugin_defs("include/plugin.defs"); 489 490 # Also read from any plugin local or suite specific plugin.defs 491 for (glob "$basedir/plugin/*/tests/mtr/plugin.defs". 492 " $basedir/internal/plugin/*/tests/mtr/plugin.defs". 493 " suite/*/plugin.defs") { 494 read_plugin_defs($_); 495 } 496 497 # Simplify reference to semisync plugins 498 $ENV{'SEMISYNC_PLUGIN_OPT'}= $ENV{'SEMISYNC_MASTER_PLUGIN_OPT'}; 499 500 # Create child processes 501 my %children; 502 for my $child_num (1..$opt_parallel){ 503 my $child_pid= My::SafeProcess::Base::_safe_fork(); 504 if ($child_pid == 0){ 505 $server= undef; # Close the server port in child 506 $tests= {}; # Don't need the tests list in child 507 508 # Use subdir of var and tmp unless only one worker 509 if ($opt_parallel > 1) { 510 set_vardir("$opt_vardir/$child_num"); 511 $opt_tmpdir= "$opt_tmpdir/$child_num"; 512 } 513 514 init_timers(); 515 run_worker($server_port, $child_num); 516 exit(1); 517 } 518 519 $children{$child_pid}= 1; 520 } 521 ####################################################################### 522 523 mtr_report(); 524 mtr_print_thick_line(); 525 mtr_print_header($opt_parallel > 1); 526 527 mark_time_used('init'); 528 529 my $completed= run_test_server($server, $tests, $opt_parallel); 530 531 exit(0) if $opt_start_exit; 532 533 # Send Ctrl-C to any children still running 534 kill("INT", keys(%children)); 535 536 if (!IS_WINDOWS) { 537 # Wait for children to exit 538 foreach my $pid (keys %children) 539 { 540 my $ret_pid= waitpid($pid, 0); 541 if ($ret_pid != $pid){ 542 mtr_report("Unknown process $ret_pid exited"); 543 } 544 else { 545 delete $children{$ret_pid}; 546 } 547 } 548 } 549 550 if ( not $completed ) { 551 mtr_error("Test suite aborted"); 552 } 553 554 my $aggregated_shutdown_report = ''; 555 my $aggregated_valgrind_report = ''; 556 foreach my $t (@$completed) { 557 if ($t->{name} eq "shutdown_report") { 558 if (defined $t->{comment} && $t->{comment} ne '') { 559 $aggregated_shutdown_report .= $t->{comment}; 560 } 561 if ($opt_valgrind && defined $t->{valgrind_comment} 562 && $t->{valgrind_comment} ne '') { 563 $aggregated_valgrind_report .= $t->{valgrind_comment}; 564 } 565 } 566 } 567 568 @$completed = grep {$_->{name} ne "shutdown_report"} @$completed; 569 570 if (@$completed != $num_tests) { 571 # Not all tests completed 572 mtr_report(); 573 mtr_report("Only ", int(@$completed), " of $num_tests completed."); 574 mtr_report("Not all tests completed. This means that a test scheduled for a worker did not report anything, the worker most likely crashed."); 575 576 my %comp; 577 578 foreach ( @$completed ) { 579 $comp{$_->{name}} = 1; 580 } 581 for (my $i = 0 ; $i <= @$all_tests ; $i++) { 582 my $t = $all_tests->[$i]; 583 if (exists $t->{name} && !exists $comp{$t->{name}}) { 584 mtr_report("Missing result for testcase: ", $t->{name}); 585 } 586 } 587 } 588 589 mark_time_used('init'); 590 591 push @$completed, run_ctest() if $opt_ctest; 592 593 # Create minimalistic "test" for the reporting failures at shutdown 594 my $tinfo = My::Test->new( 595 name => 'shutdown_report', 596 shortname => 'shutdown_report', 597 ); 598 599 # Set dummy worker id to align report with normal tests 600 $tinfo->{worker} = 0 if $opt_parallel > 1; 601 if ($shutdown_report && $aggregated_shutdown_report ne '') { 602 $tinfo->{result} = 'MTR_RES_FAILED'; 603 $tinfo->{comment} = "Mysqld reported failures at shutdown: \n$aggregated_shutdown_report"; 604 $tinfo->{failures} = 1; 605 } else { 606 $tinfo->{result} = 'MTR_RES_PASSED'; 607 } 608 mtr_report_test($tinfo); 609 report_option('prev_report_length', 0); 610 push @$completed, $tinfo; 611 612 if ($opt_valgrind) { 613 # Create minimalistic "test" for the reporting 614 my $tinfo = My::Test->new 615 ( 616 name => 'valgrind_report', 617 ); 618 # Set dummy worker id to align report with normal tests 619 $tinfo->{worker} = 0 if $opt_parallel > 1; 620 if ($aggregated_valgrind_report ne '') { 621 $tinfo->{result}= 'MTR_RES_FAILED'; 622 $tinfo->{comment}= "Valgrind reported failures at shutdown: \n$aggregated_valgrind_report"; 623 $tinfo->{failures}= 1; 624 } else { 625 $tinfo->{result}= 'MTR_RES_PASSED'; 626 } 627 mtr_report_test($tinfo); 628 mtr_report_test_subunit($tinfo); 629 push @$completed, $tinfo; 630 } 631 632 mtr_print_line(); 633 634 if ( $opt_gcov ) { 635 gcov_collect($bindir, $opt_gcov_exe, 636 $opt_gcov_msg, $opt_gcov_err); 637 } 638 639 if ($ctest_report) { 640 print "$ctest_report\n"; 641 mtr_print_line(); 642 } 643 644 if ($opt_ctest) { 645 find({ wanted => sub { 646 my $core_file= $File::Find::name; 647 my $core_name= basename($core_file); 648 649 if (is_core_dump($core_name)) { 650 mtr_report(" - found '$core_file'"); 651 652 My::CoreDump->show($core_file, "", 1); 653 } 654 }}, $bindir); 655 } 656 657 print_total_times($opt_parallel) if $opt_report_times; 658 659 report_stats("Completed", $completed); 660 661 remove_vardir_subs() if $opt_clean_vardir; 662 663 exit(0); 664} 665 666 667sub report_stats($$;$) { 668 my ($prefix, $tests, $skip_error) = @_; 669 670 if ($opt_junit_output) { 671 mtr_report_stats_junit($tests, $opt_junit_output, $opt_junit_package); 672 } 673 674 mtr_report_stats($prefix, $tests, $skip_error); 675} 676 677 678sub run_test_server ($$$) { 679 my ($server, $tests, $childs) = @_; 680 681 my $num_saved_cores= 0; # Number of core files saved in vardir/log/ so far. 682 my $num_saved_datadir= 0; # Number of datadirs saved in vardir/log/ so far. 683 my $num_failed_test= 0; # Number of tests failed so far 684 685 # Scheduler variables 686 my $max_ndb= $ENV{MTR_MAX_NDB} || $childs / 2; 687 $max_ndb = $childs if $max_ndb > $childs; 688 $max_ndb = 1 if $max_ndb < 1; 689 my $num_ndb_tests= 0; 690 691 my $completed= []; 692 my %running; 693 my $result; 694 my $exe_mysqld= find_mysqld($basedir) || ""; # Used as hint to CoreDump 695 696 my $suite_timeout= start_timer(suite_timeout()); 697 698 my $s= IO::Select->new(); 699 $s->add($server); 700 while (1) { 701 mark_time_used('admin'); 702 my @ready = $s->can_read(1); # Wake up once every second 703 mark_time_idle(); 704 foreach my $sock (@ready) { 705 if ($sock == $server) { 706 # New client connected 707 my $child= $sock->accept(); 708 mtr_verbose("Client connected"); 709 $s->add($child); 710 print $child "HELLO\n"; 711 } 712 else { 713 my $line= <$sock>; 714 if (!defined $line) { 715 # Client disconnected 716 mtr_verbose("Child closed socket"); 717 $s->remove($sock); 718 if (--$childs == 0){ 719 return $completed; 720 } 721 next; 722 } 723 chomp($line); 724 725 if ($line eq 'TESTRESULT'){ 726 $result= My::Test::read_test($sock); 727 # $result->print_test(); 728 729 # Report test status 730 mtr_report_test($result); 731 mtr_report_test_subunit($result); 732 733 if ( $result->is_failed() ) { 734 735 # Save the workers "savedir" in var/log 736 my $worker_savedir= $result->{savedir}; 737 my $worker_savename= basename($worker_savedir); 738 my $savedir= "$opt_vardir/log/$worker_savename"; 739 740 if ($opt_max_save_datadir > 0 && 741 $num_saved_datadir >= $opt_max_save_datadir) 742 { 743 mtr_report(" - skipping '$worker_savedir/'"); 744 rmtree($worker_savedir); 745 } 746 else 747 { 748 rename($worker_savedir, $savedir) if $worker_savedir ne $savedir; 749 750 # Look for the test log file and put that in savedir location 751 my $logfile= "$result->{shortname}" . ".log"; 752 my $logfilepath= dirname($worker_savedir) . "/" . $logfile; 753 move($logfilepath, $savedir); 754 mtr_report(" - the logfile can be found in '$savedir/$logfile'"); 755 756 # Move any core files from e.g. mysqltest 757 foreach my $coref (glob("core*"), glob("*.dmp")) 758 { 759 mtr_report(" - found '$coref', moving it to '$savedir'"); 760 move($coref, $savedir); 761 } 762 if ($opt_max_save_core > 0) { 763 # Limit number of core files saved 764 find({ no_chdir => 1, 765 wanted => sub { 766 my $core_file= $File::Find::name; 767 my $core_name= basename($core_file); 768 769 if (is_core_dump($core_name)) { 770 mtr_report(" - found '$core_name'", 771 "($num_saved_cores/$opt_max_save_core)"); 772 773 My::CoreDump->show($core_file, $exe_mysqld, $opt_parallel); 774 775 if ($num_saved_cores >= $opt_max_save_core) { 776 mtr_report(" - deleting it, already saved", 777 "$opt_max_save_core"); 778 unlink("$core_file"); 779 } else { 780 mtr_compress_file($core_file) unless @opt_cases; 781 } 782 ++$num_saved_cores; 783 } 784 } 785 }, 786 $savedir); 787 } 788 } 789 resfile_print_test(); 790 $num_saved_datadir++; 791 $num_failed_test++ unless ($result->{retries} || 792 $result->{exp_fail}); 793 794 if ( !$opt_force ) { 795 # Test has failed, force is off 796 push(@$completed, $result); 797 return $completed unless $result->{'dont_kill_server'}; 798 # Prevent kill of server, to get valgrind report 799 print $sock "BYE\n"; 800 next; 801 } 802 elsif ($opt_max_test_fail > 0 and 803 $num_failed_test >= $opt_max_test_fail) { 804 push(@$completed, $result); 805 report_stats("Too many failed", $completed, 1); 806 mtr_report("Too many tests($num_failed_test) failed!", 807 "Terminating..."); 808 return undef; 809 } 810 } 811 812 resfile_print_test(); 813 # Retry test run after test failure 814 my $retries= $result->{retries} || 2; 815 my $test_has_failed= $result->{failures} || 0; 816 if ($test_has_failed and $retries <= $opt_retry){ 817 # Test should be run one more time unless it has failed 818 # too many times already 819 my $tname= $result->{name}; 820 my $failures= $result->{failures}; 821 if ($opt_retry > 1 and $failures >= $opt_retry_failure) 822 { 823 mtr_report("\nTest $tname has failed $failures times,", 824 "no more retries!\n"); 825 } 826 else 827 { 828 mtr_report("\nRetrying test $tname, ". 829 "attempt($retries/$opt_retry)...\n"); 830 delete($result->{result}); 831 $result->{retries}= $retries + 1; 832 $result->write_test($sock, 'TESTCASE'); 833 next; 834 } 835 } 836 837 # Repeat test $opt_repeat number of times 838 my $repeat= $result->{repeat} || 1; 839 # Don't repeat if test was skipped 840 if ($repeat < $opt_repeat && $result->{'result'} ne 'MTR_RES_SKIPPED') 841 { 842 $result->{retries}= 0; 843 $result->{rep_failures}++ if $result->{failures}; 844 $result->{failures}= 0; 845 delete($result->{result}); 846 $result->{repeat}= $repeat+1; 847 $result->write_test($sock, 'TESTCASE'); 848 next; 849 } 850 851 # Remove from list of running 852 mtr_error("'", $result->{name},"' is not known to be running") 853 unless delete $running{$result->key()}; 854 855 # Update scheduler variables 856 $num_ndb_tests-- if ($result->{ndb_test}); 857 858 # Save result in completed list 859 push(@$completed, $result); 860 861 } 862 elsif ($line eq 'START'){ 863 ; # Send first test 864 } 865 elsif ($line =~ /^SPENT/) { 866 add_total_times($line); 867 } 868 elsif ($line eq 'SHUTDOWN_REPORT') { 869 # Mysqld detected crash during shutdown 870 $shutdown_report = 1; 871 push(@$completed, My::Test::read_test($sock)); 872 } else { 873 mtr_error("Unknown response: '$line' from client"); 874 } 875 876 # Find next test to schedule 877 # - Try to use same configuration as worker used last time 878 # - Limit number of parallel ndb tests 879 880 my $next; 881 my $second_best; 882 for(my $i= 0; $i <= @$tests; $i++) 883 { 884 my $t= $tests->[$i]; 885 886 last unless defined $t; 887 888 if (run_testcase_check_skip_test($t)){ 889 # Move the test to completed list 890 #mtr_report("skip - Moving test $i to completed"); 891 push(@$completed, splice(@$tests, $i, 1)); 892 893 # Since the test at pos $i was taken away, next 894 # test will also be at $i -> redo 895 redo; 896 } 897 898 # Limit number of parallell NDB tests 899 if ($t->{ndb_test} and $num_ndb_tests >= $max_ndb){ 900 #mtr_report("Skipping, num ndb is already at max, $num_ndb_tests"); 901 next; 902 } 903 904 # Second best choice is the first that does not fulfill 905 # any of the above conditions 906 if (!defined $second_best){ 907 #mtr_report("Setting second_best to $i"); 908 $second_best= $i; 909 } 910 911 # Smart allocation of next test within this thread. 912 913 if ($opt_reorder and $opt_parallel > 1 and defined $result) 914 { 915 my $wid= $result->{worker}; 916 # Reserved for other thread, try next 917 next if (defined $t->{reserved} and $t->{reserved} != $wid); 918 if (! defined $t->{reserved}) 919 { 920 # Force-restart not relevant when comparing *next* test 921 $t->{criteria} =~ s/force-restart$/no-restart/; 922 my $criteria= $t->{criteria}; 923 # Reserve similar tests for this worker, but not too many 924 my $maxres= (@$tests - $i) / $opt_parallel + 1; 925 for (my $j= $i+1; $j <= $i + $maxres; $j++) 926 { 927 my $tt= $tests->[$j]; 928 last unless defined $tt; 929 last if $tt->{criteria} ne $criteria; 930 $tt->{reserved}= $wid; 931 } 932 } 933 } 934 935 # At this point we have found next suitable test 936 $next= splice(@$tests, $i, 1); 937 last; 938 } 939 940 # Use second best choice if no other test has been found 941 if (!$next and defined $second_best){ 942 #mtr_report("Take second best choice $second_best"); 943 mtr_error("Internal error, second best too large($second_best)") 944 if $second_best > $#$tests; 945 $next= splice(@$tests, $second_best, 1); 946 delete $next->{reserved}; 947 } 948 949 if ($next) { 950 # We don't need this any more 951 delete $next->{criteria}; 952 $next->write_test($sock, 'TESTCASE'); 953 $running{$next->key()}= $next; 954 $num_ndb_tests++ if ($next->{ndb_test}); 955 } 956 else { 957 # No more test, tell child to exit 958 #mtr_report("Saying BYE to child"); 959 print $sock "BYE\n"; 960 } 961 } 962 } 963 964 # ---------------------------------------------------- 965 # Check if test suite timer expired 966 # ---------------------------------------------------- 967 if ( has_expired($suite_timeout) ) 968 { 969 report_stats("Timeout", $completed, 1); 970 mtr_report("Test suite timeout! Terminating..."); 971 return undef; 972 } 973 } 974} 975 976 977sub run_worker ($) { 978 my ($server_port, $thread_num)= @_; 979 980 $SIG{INT}= sub { exit(1); }; 981 982 # Connect to server 983 my $server = new IO::Socket::INET 984 ( 985 PeerAddr => 'localhost', 986 PeerPort => $server_port, 987 Proto => 'tcp' 988 ); 989 mtr_error("Could not connect to server at port $server_port: $!") 990 unless $server; 991 992 # -------------------------------------------------------------------------- 993 # Set worker name 994 # -------------------------------------------------------------------------- 995 report_option('name',"worker[$thread_num]"); 996 997 # -------------------------------------------------------------------------- 998 # Set different ports per thread 999 # -------------------------------------------------------------------------- 1000 set_build_thread_ports($thread_num); 1001 1002 # -------------------------------------------------------------------------- 1003 # Turn off verbosity in workers, unless explicitly specified 1004 # -------------------------------------------------------------------------- 1005 report_option('verbose', undef) if ($opt_verbose == 0); 1006 1007 environment_setup(); 1008 1009 # Read hello from server which it will send when shared 1010 # resources have been setup 1011 my $hello= <$server>; 1012 1013 setup_vardir(); 1014 check_running_as_root(); 1015 1016 if ( using_extern() ) { 1017 create_config_file_for_extern(%opts_extern); 1018 } 1019 1020 # Ask server for first test 1021 print $server "START\n"; 1022 1023 mark_time_used('init'); 1024 1025 while (my $line= <$server>){ 1026 chomp($line); 1027 if ($line eq 'TESTCASE'){ 1028 my $test= My::Test::read_test($server); 1029 #$test->print_test(); 1030 1031 # Clear comment and logfile, to avoid 1032 # reusing them from previous test 1033 delete($test->{'comment'}); 1034 delete($test->{'logfile'}); 1035 1036 # A sanity check. Should this happen often we need to look at it. 1037 if (defined $test->{reserved} && $test->{reserved} != $thread_num) { 1038 my $tres= $test->{reserved}; 1039 mtr_warning("Test reserved for w$tres picked up by w$thread_num"); 1040 } 1041 $test->{worker} = $thread_num if $opt_parallel > 1; 1042 1043 run_testcase($test); 1044 #$test->{result}= 'MTR_RES_PASSED'; 1045 # Send it back, now with results set 1046 #$test->print_test(); 1047 $test->write_test($server, 'TESTRESULT'); 1048 mark_time_used('restart'); 1049 } 1050 elsif ($line eq 'BYE'){ 1051 mtr_report("Server said BYE"); 1052 my $found_err = 0; 1053 my $valgrind_report_text = ''; 1054 1055 stop_all_servers($opt_shutdown_timeout); 1056 1057 if ($opt_valgrind_mysqld) { 1058 $valgrind_report_text = valgrind_exit_reports(); 1059 } 1060 1061 if ($shutdown_report || $valgrind_report_text) { 1062 my $test = My::Test->new( 1063 name => 'shutdown_report', 1064 comment => $shutdown_report_text, 1065 valgrind_comment => $valgrind_report_text, 1066 ); 1067 $test->write_test($server, "SHUTDOWN_REPORT"); 1068 $found_err = 1; 1069 } 1070 1071 mark_time_used('restart'); 1072 1073 if ( $opt_gprof ) { 1074 gprof_collect (find_mysqld($basedir), keys %gprof_dirs); 1075 } 1076 1077 mark_time_used('admin'); 1078 print_times_used($server, $thread_num); 1079 exit($found_err); 1080 } 1081 else { 1082 mtr_error("Could not understand server, '$line'"); 1083 } 1084 } 1085 1086 stop_all_servers(); 1087 1088 exit(1); 1089} 1090 1091# Search server logs for any crashes during mysqld shutdown 1092sub shutdown_exit_reports() { 1093 my $found_report = 0; 1094 my $clean_shutdown = 0; 1095 my $all_exit_reports = {}; 1096 1097 foreach my $log_file (keys %mysqld_logs) { 1098 my @culprits = (); 1099 my $crash_rep = ""; 1100 1101 my $LOGF = IO::File->new($log_file) or 1102 mtr_error("Could not open file '$log_file' for reading: $!"); 1103 1104 while (my $line = <$LOGF>) { 1105 if ($line =~ /^CURRENT_TEST: (.+)$/) { 1106 my $testname = $1; 1107 # If we have a report, report it if needed and start new list of tests 1108 if ($found_report or $clean_shutdown) { 1109 # Make ready to collect new report 1110 @culprits = (); 1111 $found_report = 0; 1112 $clean_shutdown = 0; 1113 $crash_rep = ""; 1114 } 1115 push(@culprits, $testname); 1116 next; 1117 } 1118 1119 # Clean shutdown 1120 $clean_shutdown = 1 if $line =~ /.*Shutdown completed.*/; 1121 1122 # Mysqld crash at shutdown 1123 $found_report = 1 if ($line =~ /.*Assertion.*/ or $line =~ /.*mysqld got signal.*/ 1124 or $line =~ /.*mysqld got exception.*/); 1125 1126 if ($found_report) { 1127 $crash_rep .= $line; 1128 } 1129 } 1130 1131 my $report_text = ''; 1132 1133 if ($found_report) { 1134 $report_text = $crash_rep; 1135 } else { 1136 # Print last 100 lines of log file since shutdown failed 1137 # for some reason. 1138 $report_text = mtr_lastlinesfromfile($log_file, 100); 1139 } 1140 1141 $all_exit_reports->{$log_file} = { 1142 text => $report_text, 1143 after_tests => [@culprits], 1144 }; 1145 $LOGF = undef; 1146 } 1147 1148 return $all_exit_reports; 1149} 1150 1151sub ignore_option { 1152 my ($opt, $value)= @_; 1153 mtr_report("Ignoring option '$opt'"); 1154} 1155 1156 1157 1158# Setup any paths that are $opt_vardir related 1159sub set_vardir { 1160 my ($vardir)= @_; 1161 1162 $opt_vardir= $vardir; 1163 1164 $path_vardir_trace= $opt_vardir; 1165 # Chop off any "c:", DBUG likes a unix path ex: c:/src/... => /src/... 1166 $path_vardir_trace=~ s/^\w://; 1167 1168 # Location of my.cnf that all clients use 1169 $path_config_file= "$opt_vardir/my.cnf"; 1170 1171 $path_testlog= "$opt_vardir/log/mysqltest.log"; 1172 $path_current_testlog= "$opt_vardir/log/current_test"; 1173 1174} 1175 1176 1177sub print_global_resfile { 1178 resfile_global("start_time", isotime $^T); 1179 resfile_global("user_id", $<); 1180 resfile_global("embedded-server", $opt_embedded_server ? 1 : 0); 1181 resfile_global("ps-protocol", $opt_ps_protocol ? 1 : 0); 1182 resfile_global("sp-protocol", $opt_sp_protocol ? 1 : 0); 1183 resfile_global("view-protocol", $opt_view_protocol ? 1 : 0); 1184 resfile_global("cursor-protocol", $opt_cursor_protocol ? 1 : 0); 1185 resfile_global("ssl", $opt_ssl ? 1 : 0); 1186 resfile_global("compress", $opt_compress ? 1 : 0); 1187 resfile_global("parallel", $opt_parallel); 1188 resfile_global("check-testcases", $opt_check_testcases ? 1 : 0); 1189 resfile_global("mysqld", \@opt_extra_mysqld_opt); 1190 resfile_global("debug", $opt_debug ? 1 : 0); 1191 resfile_global("gcov", $opt_gcov ? 1 : 0); 1192 resfile_global("gprof", $opt_gprof ? 1 : 0); 1193 resfile_global("valgrind", $opt_valgrind ? 1 : 0); 1194 resfile_global("callgrind", $opt_callgrind ? 1 : 0); 1195 resfile_global("helgrind", $opt_helgrind ? 1 : 0); 1196 resfile_global("mem", $opt_mem ? 1 : 0); 1197 resfile_global("tmpdir", $opt_tmpdir); 1198 resfile_global("vardir", $opt_vardir); 1199 resfile_global("fast", $opt_fast ? 1 : 0); 1200 resfile_global("force-restart", $opt_force_restart ? 1 : 0); 1201 resfile_global("reorder", $opt_reorder ? 1 : 0); 1202 resfile_global("sleep", $opt_sleep); 1203 resfile_global("repeat", $opt_repeat); 1204 resfile_global("user", $opt_user); 1205 resfile_global("testcase-timeout", $opt_testcase_timeout); 1206 resfile_global("suite-timeout", $opt_suite_timeout); 1207 resfile_global("shutdown-timeout", $opt_shutdown_timeout ? 1 : 0); 1208 resfile_global("warnings", $opt_warnings ? 1 : 0); 1209 resfile_global("max-connections", $opt_max_connections); 1210# resfile_global("default-myisam", $opt_default_myisam ? 1 : 0); 1211 resfile_global("product", "MySQL"); 1212 # Somewhat hacky code to convert numeric version back to dot notation 1213 my $v1= int($mysql_version_id / 10000); 1214 my $v2= int(($mysql_version_id % 10000)/100); 1215 my $v3= $mysql_version_id % 100; 1216 resfile_global("version", "$v1.$v2.$v3"); 1217} 1218 1219 1220 1221sub command_line_setup { 1222 my $opt_comment; 1223 my $opt_usage; 1224 my $opt_list_options; 1225 1226 # Read the command line options 1227 # Note: Keep list in sync with usage at end of this file 1228 Getopt::Long::Configure("pass_through"); 1229 my %options=( 1230 # Control what engine/variation to run 1231 'embedded-server' => \$opt_embedded_server, 1232 'ps-protocol' => \$opt_ps_protocol, 1233 'sp-protocol' => \$opt_sp_protocol, 1234 'view-protocol' => \$opt_view_protocol, 1235 'opt-trace-protocol' => \$opt_trace_protocol, 1236 'explain-protocol' => \$opt_explain_protocol, 1237 'json-explain-protocol' => \$opt_json_explain_protocol, 1238 'cursor-protocol' => \$opt_cursor_protocol, 1239 'ssl|with-openssl' => \$opt_ssl, 1240 'skip-ssl' => \$opt_skip_ssl, 1241 'compress' => \$opt_compress, 1242 'vs-config=s' => \$opt_vs_config, 1243 1244 # Max number of parallel threads to use 1245 'parallel=s' => \$opt_parallel, 1246 1247 # Config file to use as template for all tests 1248 'defaults-file=s' => \&collect_option, 1249 # Extra config file to append to all generated configs 1250 'defaults-extra-file=s' => \&collect_option, 1251 1252 # Control what test suites or cases to run 1253 'force' => \$opt_force, 1254 'with-ndbcluster-only' => \&collect_option, 1255 'ndb|include-ndbcluster' => \$opt_include_ndbcluster, 1256 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster, 1257 'suite|suites=s' => \$opt_suites, 1258 'skip-rpl' => \&collect_option, 1259 'skip-test=s' => \&collect_option, 1260 'do-test=s' => \&collect_option, 1261 'start-from=s' => \&collect_option, 1262 'big-test' => \$opt_big_test, 1263 'combination=s' => \@opt_combinations, 1264 'skip-combinations' => \&collect_option, 1265 'experimental=s' => \@opt_experimentals, 1266 # skip-im is deprecated and silently ignored 1267 'skip-im' => \&ignore_option, 1268 1269 # Specify ports 1270 'build-thread|mtr-build-thread=i' => \$opt_build_thread, 1271 'port-base|mtr-port-base=i' => \$opt_port_base, 1272 1273 # Test case authoring 1274 'record' => \$opt_record, 1275 'check-testcases!' => \$opt_check_testcases, 1276 'mark-progress' => \$opt_mark_progress, 1277 1278 # Extra options used when starting mysqld 1279 'mysqld=s' => \@opt_extra_mysqld_opt, 1280 'mysqld-env=s' => \@opt_mysqld_envs, 1281 1282 # Run test on running server 1283 'extern=s' => \%opts_extern, # Append to hash 1284 1285 # Debugging 1286 'debug' => \$opt_debug, 1287 'debug-common' => \$opt_debug_common, 1288 'debug-server' => \$opt_debug_server, 1289 'gdb' => \$opt_gdb, 1290 'client-gdb' => \$opt_client_gdb, 1291 'manual-gdb' => \$opt_manual_gdb, 1292 "lldb" => \$opt_lldb, 1293 'manual-lldb' => \$opt_manual_lldb, 1294 'boot-gdb' => \$opt_boot_gdb, 1295 'manual-debug' => \$opt_manual_debug, 1296 'ddd' => \$opt_ddd, 1297 'client-ddd' => \$opt_client_ddd, 1298 'manual-ddd' => \$opt_manual_ddd, 1299 'boot-ddd' => \$opt_boot_ddd, 1300 'dbx' => \$opt_dbx, 1301 'client-dbx' => \$opt_client_dbx, 1302 'manual-dbx' => \$opt_manual_dbx, 1303 'debugger=s' => \$opt_debugger, 1304 'boot-dbx' => \$opt_boot_dbx, 1305 'client-debugger=s' => \$opt_client_debugger, 1306 'strace-server' => \$opt_strace_server, 1307 'strace-client' => \$opt_strace_client, 1308 'max-save-core=i' => \$opt_max_save_core, 1309 'max-save-datadir=i' => \$opt_max_save_datadir, 1310 'max-test-fail=i' => \$opt_max_test_fail, 1311 1312 # Coverage, profiling etc 1313 'gcov' => \$opt_gcov, 1314 'gprof' => \$opt_gprof, 1315 'valgrind|valgrind-all' => \$opt_valgrind, 1316 'valgrind-mysqltest' => \$opt_valgrind_mysqltest, 1317 'valgrind-mysqld' => \$opt_valgrind_mysqld, 1318 'valgrind-options=s' => sub { 1319 my ($opt, $value)= @_; 1320 # Deprecated option unless it's what we know pushbuild uses 1321 if ($value eq "--gen-suppressions=all --show-reachable=yes") { 1322 push(@valgrind_args, $_) for (split(' ', $value)); 1323 return; 1324 } 1325 die("--valgrind-options=s is deprecated. Use ", 1326 "--valgrind-option=s, to be specified several", 1327 " times if necessary"); 1328 }, 1329 'valgrind-option=s' => \@valgrind_args, 1330 'valgrind-path=s' => \$opt_valgrind_path, 1331 'callgrind' => \$opt_callgrind, 1332 'helgrind' => \$opt_helgrind, 1333 'debug-sync-timeout=i' => \$opt_debug_sync_timeout, 1334 1335 # Directories 1336 'tmpdir=s' => \$opt_tmpdir, 1337 'vardir=s' => \$opt_vardir, 1338 'mem' => \$opt_mem, 1339 'clean-vardir' => \$opt_clean_vardir, 1340 'client-bindir=s' => \$path_client_bindir, 1341 'client-libdir=s' => \$path_client_libdir, 1342 1343 # Misc 1344 'report-features' => \$opt_report_features, 1345 'comment=s' => \$opt_comment, 1346 'fast' => \$opt_fast, 1347 'force-restart' => \$opt_force_restart, 1348 'reorder!' => \$opt_reorder, 1349 'enable-disabled' => \&collect_option, 1350 'verbose+' => \$opt_verbose, 1351 'verbose-restart' => \&report_option, 1352 'sleep=i' => \$opt_sleep, 1353 'start-dirty' => \$opt_start_dirty, 1354 'start-and-exit' => \$opt_start_exit, 1355 'start' => \$opt_start, 1356 'user-args' => \$opt_user_args, 1357 'wait-all' => \$opt_wait_all, 1358 'print-testcases' => \&collect_option, 1359 'repeat=i' => \$opt_repeat, 1360 'retry=i' => \$opt_retry, 1361 'retry-failure=i' => \$opt_retry_failure, 1362 'timer!' => \&report_option, 1363 'user=s' => \$opt_user, 1364 'testcase-timeout=i' => \$opt_testcase_timeout, 1365 'suite-timeout=i' => \$opt_suite_timeout, 1366 'shutdown-timeout=i' => \$opt_shutdown_timeout, 1367 'warnings!' => \$opt_warnings, 1368 'timestamp' => \&report_option, 1369 'timediff' => \&report_option, 1370 'max-connections=i' => \$opt_max_connections, 1371 'default-myisam!' => \&collect_option, 1372 'report-times' => \$opt_report_times, 1373 'result-file' => \$opt_resfile, 1374 'unit-tests!' => \$opt_ctest, 1375 'unit-tests-report!' => \$opt_ctest_report, 1376 'stress=s' => \$opt_stress, 1377 'junit-output=s' => \$opt_junit_output, 1378 'junit-package=s' => \$opt_junit_package, 1379 1380 'help|h' => \$opt_usage, 1381 # list-options is internal, not listed in help 1382 'list-options' => \$opt_list_options, 1383 'skip-test-list=s' => \@opt_skip_test_list 1384 ); 1385 1386 GetOptions(%options) or usage("Can't read options"); 1387 1388 usage("") if $opt_usage; 1389 list_options(\%options) if $opt_list_options; 1390 1391 # Make sure that XML::Simple support exists for JUnit output 1392 if ($opt_junit_output and !mtr_junit_supported()) { 1393 mtr_error("JUnit XML reporting is not supported. The XML::Simple package", 1394 "could not be loaded."); 1395 } 1396 1397 # -------------------------------------------------------------------------- 1398 # Setup verbosity 1399 # -------------------------------------------------------------------------- 1400 if ($opt_verbose != 0){ 1401 report_option('verbose', $opt_verbose); 1402 } 1403 1404 if ( -d "../sql" ) 1405 { 1406 $source_dist= 1; 1407 } 1408 1409 # Find the absolute path to the test directory 1410 $glob_mysql_test_dir= cwd(); 1411 if ($glob_mysql_test_dir =~ / /) 1412 { 1413 die("Working directory \"$glob_mysql_test_dir\" contains space\n". 1414 "Bailing out, cannot function properly with space in path"); 1415 } 1416 if (IS_CYGWIN) 1417 { 1418 # Use mixed path format i.e c:/path/to/ 1419 $glob_mysql_test_dir= mixed_path($glob_mysql_test_dir); 1420 } 1421 1422 # In most cases, the base directory we find everything relative to, 1423 # is the parent directory of the "mysql-test" directory. For source 1424 # distributions, TAR binary distributions and some other packages. 1425 $basedir= dirname($glob_mysql_test_dir); 1426 1427 # In the RPM case, binaries and libraries are installed in the 1428 # default system locations, instead of having our own private base 1429 # directory. And we install "/usr/share/mysql-test". Moving up one 1430 # more directory relative to "mysql-test" gives us a usable base 1431 # directory for RPM installs. 1432 if ( ! $source_dist and ! -d "$basedir/bin" ) 1433 { 1434 $basedir= dirname($basedir); 1435 } 1436 1437 # Respect MTR_BINDIR variable, which is typically set in to the 1438 # build directory in out-of-source builds. 1439 $bindir=$ENV{MTR_BINDIR}||$basedir; 1440 1441 # Look for the client binaries directory 1442 if ($path_client_bindir) 1443 { 1444 # --client-bindir=path set on command line, check that the path exists 1445 $path_client_bindir= mtr_path_exists($path_client_bindir); 1446 } 1447 else 1448 { 1449 $path_client_bindir= mtr_path_exists("$bindir/client_release", 1450 "$bindir/client_debug", 1451 vs_config_dirs('client', ''), 1452 "$bindir/client", 1453 "$bindir/bin"); 1454 } 1455 1456 # Look for language files and charsetsdir, use same share 1457 $path_language= mtr_path_exists("$bindir/share/mysql", 1458 "$bindir/sql/share", 1459 "$bindir/share"); 1460 my $path_share= $path_language; 1461 $path_charsetsdir = mtr_path_exists("$basedir/share/mysql/charsets", 1462 "$basedir/sql/share/charsets", 1463 "$basedir/share/charsets"); 1464 1465 ($auth_plugin)= find_plugin("auth_test_plugin", "plugin/auth"); 1466 1467 # --debug[-common] implies we run debug server 1468 $opt_debug_server= 1 if $opt_debug || $opt_debug_common; 1469 1470 if (using_extern()) 1471 { 1472 # Connect to the running mysqld and find out what it supports 1473 collect_mysqld_features_from_running_server(); 1474 } 1475 else 1476 { 1477 # Run the mysqld to find out what features are available 1478 collect_mysqld_features(); 1479 } 1480 1481 if ( $opt_comment ) 1482 { 1483 mtr_report(); 1484 mtr_print_thick_line('#'); 1485 mtr_report("# $opt_comment"); 1486 mtr_print_thick_line('#'); 1487 } 1488 1489 if ( @opt_experimentals ) 1490 { 1491 # $^O on Windows considered not generic enough 1492 my $plat= (IS_WINDOWS) ? 'windows' : $^O; 1493 1494 # read the list of experimental test cases from the files specified on 1495 # the command line 1496 $experimental_test_cases = []; 1497 foreach my $exp_file (@opt_experimentals) 1498 { 1499 open(FILE, "<", $exp_file) 1500 or mtr_error("Can't read experimental file: $exp_file"); 1501 mtr_report("Using experimental file: $exp_file"); 1502 while(<FILE>) { 1503 chomp; 1504 # remove comments (# foo) at the beginning of the line, or after a 1505 # blank at the end of the line 1506 s/(\s+|^)#.*$//; 1507 # If @ platform specifier given, use this entry only if it contains 1508 # @<platform> or @!<xxx> where xxx != platform 1509 if (/\@.*/) 1510 { 1511 next if (/\@!$plat/); 1512 next unless (/\@$plat/ or /\@!/); 1513 # Then remove @ and everything after it 1514 s/\@.*$//; 1515 } 1516 # remove whitespace 1517 s/^\s+//; 1518 s/\s+$//; 1519 # if nothing left, don't need to remember this line 1520 if ( $_ eq "" ) { 1521 next; 1522 } 1523 # remember what is left as the name of another test case that should be 1524 # treated as experimental 1525 print " - $_\n"; 1526 push @$experimental_test_cases, $_; 1527 } 1528 close FILE; 1529 } 1530 } 1531 1532 foreach my $arg ( @ARGV ) 1533 { 1534 if ( $arg =~ /^--skip-/ ) 1535 { 1536 push(@opt_extra_mysqld_opt, $arg); 1537 } 1538 elsif ( $arg =~ /^--$/ ) 1539 { 1540 # It is an effect of setting 'pass_through' in option processing 1541 # that the lone '--' separating options from arguments survives, 1542 # simply ignore it. 1543 } 1544 elsif ( $arg =~ /^-/ ) 1545 { 1546 usage("Invalid option \"$arg\""); 1547 } 1548 else 1549 { 1550 push(@opt_cases, $arg); 1551 } 1552 } 1553 1554 # -------------------------------------------------------------------------- 1555 # Find out type of logging that are being used 1556 # -------------------------------------------------------------------------- 1557 foreach my $arg ( @opt_extra_mysqld_opt ) 1558 { 1559 if ( $arg =~ /binlog[-_]format=(\S+)/ ) 1560 { 1561 # Save this for collect phase 1562 collect_option('binlog-format', $1); 1563 mtr_report("Using binlog format '$1'"); 1564 } 1565 } 1566 1567 1568 # -------------------------------------------------------------------------- 1569 # Find out default storage engine being used(if any) 1570 # -------------------------------------------------------------------------- 1571 foreach my $arg ( @opt_extra_mysqld_opt ) 1572 { 1573 if ( $arg =~ /default-storage-engine=(\S+)/ ) 1574 { 1575 # Save this for collect phase 1576 collect_option('default-storage-engine', $1); 1577 mtr_report("Using default engine '$1'") 1578 } 1579 if ( $arg =~ /default-tmp-storage-engine=(\S+)/ ) 1580 { 1581 # Save this for collect phase 1582 collect_option('default-tmp-storage-engine', $1); 1583 mtr_report("Using default tmp engine '$1'") 1584 } 1585 } 1586 1587 if (IS_WINDOWS and defined $opt_mem) { 1588 mtr_report("--mem not supported on Windows, ignored"); 1589 $opt_mem= undef; 1590 } 1591 1592 if ($opt_port_base ne "auto") 1593 { 1594 if (my $rem= $opt_port_base % 10) 1595 { 1596 mtr_warning ("Port base $opt_port_base rounded down to multiple of 10"); 1597 $opt_port_base-= $rem; 1598 } 1599 $opt_build_thread= $opt_port_base / 10 - 1000; 1600 } 1601 1602 # -------------------------------------------------------------------------- 1603 # Check if we should speed up tests by trying to run on tmpfs 1604 # -------------------------------------------------------------------------- 1605 if ( defined $opt_mem) 1606 { 1607 mtr_error("Can't use --mem and --vardir at the same time ") 1608 if $opt_vardir; 1609 mtr_error("Can't use --mem and --tmpdir at the same time ") 1610 if $opt_tmpdir; 1611 1612 # Search through list of locations that are known 1613 # to be "fast disks" to find a suitable location 1614 # Use --mem=<dir> as first location to look. 1615 my @tmpfs_locations= ($opt_mem, "/dev/shm", "/tmp"); 1616 1617 foreach my $fs (@tmpfs_locations) 1618 { 1619 if ( -d $fs ) 1620 { 1621 my $template= "var_${opt_build_thread}_XXXX"; 1622 $opt_mem= tempdir( $template, DIR => $fs, CLEANUP => 0); 1623 last; 1624 } 1625 } 1626 } 1627 1628 # -------------------------------------------------------------------------- 1629 # Set the "var/" directory, the base for everything else 1630 # -------------------------------------------------------------------------- 1631 if(defined $ENV{MTR_BINDIR}) 1632 { 1633 $default_vardir= "$ENV{MTR_BINDIR}/mysql-test/var"; 1634 } 1635 else 1636 { 1637 $default_vardir= "$glob_mysql_test_dir/var"; 1638 } 1639 if ( ! $opt_vardir ) 1640 { 1641 $opt_vardir= $default_vardir; 1642 } 1643 1644 # We make the path absolute, as the server will do a chdir() before usage 1645 unless ( $opt_vardir =~ m,^/, or 1646 (IS_WINDOWS and $opt_vardir =~ m,^[a-z]:[/\\],i) ) 1647 { 1648 # Make absolute path, relative test dir 1649 $opt_vardir= "$glob_mysql_test_dir/$opt_vardir"; 1650 } 1651 1652 set_vardir($opt_vardir); 1653 1654 # -------------------------------------------------------------------------- 1655 # Set the "tmp" directory 1656 # -------------------------------------------------------------------------- 1657 if ( ! $opt_tmpdir ) 1658 { 1659 $opt_tmpdir= "$opt_vardir/tmp" unless $opt_tmpdir; 1660 1661 if (check_socket_path_length("$opt_tmpdir/mysql_testsocket.sock")) 1662 { 1663 mtr_report("Too long tmpdir path '$opt_tmpdir'", 1664 " creating a shorter one..."); 1665 1666 # Create temporary directory in standard location for temporary files 1667 $opt_tmpdir= tempdir( TMPDIR => 1, CLEANUP => 0 ); 1668 mtr_report(" - using tmpdir: '$opt_tmpdir'\n"); 1669 1670 # Remember pid that created dir so it's removed by correct process 1671 $opt_tmpdir_pid= $$; 1672 } 1673 } 1674 $opt_tmpdir =~ s,/+$,,; # Remove ending slash if any 1675 1676 # -------------------------------------------------------------------------- 1677 # fast option 1678 # -------------------------------------------------------------------------- 1679 if ($opt_fast){ 1680 $opt_shutdown_timeout= 0; # Kill processes instead of nice shutdown 1681 } 1682 1683 # -------------------------------------------------------------------------- 1684 # Check parallel value 1685 # -------------------------------------------------------------------------- 1686 if ($opt_parallel ne "auto" && $opt_parallel < 1) 1687 { 1688 mtr_error("0 or negative parallel value makes no sense, use 'auto' or positive number"); 1689 } 1690 1691 # -------------------------------------------------------------------------- 1692 # Record flag 1693 # -------------------------------------------------------------------------- 1694 if ( $opt_record and ! @opt_cases ) 1695 { 1696 mtr_error("Will not run in record mode without a specific test case"); 1697 } 1698 1699 if ( $opt_record ) { 1700 # Use only one worker with --record 1701 $opt_parallel= 1; 1702 } 1703 1704 # -------------------------------------------------------------------------- 1705 # Embedded server flag 1706 # -------------------------------------------------------------------------- 1707 if ( $opt_embedded_server ) 1708 { 1709 if ( IS_WINDOWS ) 1710 { 1711 # Add the location for libmysqld.dll to the path. 1712 my $separator= ";"; 1713 my $lib_mysqld= 1714 mtr_path_exists("$bindir/lib", vs_config_dirs('libmysqld','')); 1715 if ( IS_CYGWIN ) 1716 { 1717 $lib_mysqld= posix_path($lib_mysqld); 1718 $separator= ":"; 1719 } 1720 $ENV{'PATH'}= "$ENV{'PATH'}".$separator.$lib_mysqld; 1721 } 1722 $opt_skip_ssl= 1; # Turn off use of SSL 1723 1724 # Turn off use of bin log 1725 push(@opt_extra_mysqld_opt, "--skip-log-bin"); 1726 1727 if ( using_extern() ) 1728 { 1729 mtr_error("Can't use --extern with --embedded-server"); 1730 } 1731 1732 1733 if ($opt_gdb) 1734 { 1735 mtr_warning("Silently converting --gdb to --client-gdb in embedded mode"); 1736 $opt_client_gdb= $opt_gdb; 1737 $opt_gdb= undef; 1738 } 1739 1740 if ($opt_ddd) 1741 { 1742 mtr_warning("Silently converting --ddd to --client-ddd in embedded mode"); 1743 $opt_client_ddd= $opt_ddd; 1744 $opt_ddd= undef; 1745 } 1746 1747 if ($opt_dbx) { 1748 mtr_warning("Silently converting --dbx to --client-dbx in embedded mode"); 1749 $opt_client_dbx= $opt_dbx; 1750 $opt_dbx= undef; 1751 } 1752 1753 if ($opt_debugger) 1754 { 1755 mtr_warning("Silently converting --debugger to --client-debugger in embedded mode"); 1756 $opt_client_debugger= $opt_debugger; 1757 $opt_debugger= undef; 1758 } 1759 1760 if ( $opt_gdb || $opt_ddd || $opt_manual_gdb || $opt_lldb || $opt_manual_lldb || 1761 $opt_manual_ddd || $opt_manual_debug || $opt_debugger || $opt_dbx || 1762 $opt_manual_dbx) 1763 { 1764 mtr_error("You need to use the client debug options for the", 1765 "embedded server. Ex: --client-gdb"); 1766 } 1767 } 1768 1769 # -------------------------------------------------------------------------- 1770 # Big test flags 1771 # -------------------------------------------------------------------------- 1772 if ( $opt_big_test ) 1773 { 1774 $ENV{'BIG_TEST'}= 1; 1775 } 1776 1777 # -------------------------------------------------------------------------- 1778 # Gcov flag 1779 # -------------------------------------------------------------------------- 1780 if ( ($opt_gcov or $opt_gprof) and ! $source_dist ) 1781 { 1782 mtr_error("Coverage test needs the source - please use source dist"); 1783 } 1784 1785 # -------------------------------------------------------------------------- 1786 # Check debug related options 1787 # -------------------------------------------------------------------------- 1788 if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd || 1789 $opt_manual_gdb || $opt_lldb || $opt_manual_lldb || $opt_manual_ddd || 1790 $opt_manual_debug || $opt_dbx || $opt_client_dbx || $opt_manual_dbx || 1791 $opt_debugger || $opt_client_debugger ) 1792 { 1793 # Indicate that we are using debugger 1794 $glob_debugger= 1; 1795 if ( using_extern() ) 1796 { 1797 mtr_error("Can't use --extern when using debugger"); 1798 } 1799 # Set one week timeout (check-testcase timeout will be 1/10th) 1800 $opt_testcase_timeout= 7 * 24 * 60; 1801 $opt_suite_timeout= 7 * 24 * 60; 1802 # One day to shutdown 1803 $opt_shutdown_timeout= 24 * 60; 1804 # One day for PID file creation (this is given in seconds not minutes) 1805 $opt_start_timeout= 24 * 60 * 60; 1806 } 1807 1808 # -------------------------------------------------------------------------- 1809 # Modified behavior with --start options 1810 # -------------------------------------------------------------------------- 1811 if ($opt_start or $opt_start_dirty or $opt_start_exit) { 1812 collect_option ('quick-collect', 1); 1813 $start_only= 1; 1814 } 1815 1816 # -------------------------------------------------------------------------- 1817 # Check use of user-args 1818 # -------------------------------------------------------------------------- 1819 1820 if ($opt_user_args) { 1821 mtr_error("--user-args only valid with --start options") 1822 unless $start_only; 1823 mtr_error("--user-args cannot be combined with named suites or tests") 1824 if $opt_suites || @opt_cases; 1825 } 1826 1827 # -------------------------------------------------------------------------- 1828 # Set default values for opt_ctest (--unit-tests) 1829 # -------------------------------------------------------------------------- 1830 1831 if ($opt_ctest == -1) { 1832 if (defined $opt_ctest_report && $opt_ctest_report) { 1833 # Turn on --unit-tests by default if --unit-tests-report is used 1834 $opt_ctest= 1; 1835 } elsif ($opt_suites || @opt_cases) { 1836 # Don't run ctest if tests or suites named 1837 $opt_ctest= 0; 1838 } elsif (defined $ENV{PB2WORKDIR}) { 1839 # Override: disable if running in the PB test environment 1840 $opt_ctest= 0; 1841 } 1842 } 1843 1844 # -------------------------------------------------------------------------- 1845 # Check use of wait-all 1846 # -------------------------------------------------------------------------- 1847 1848 if ($opt_wait_all && ! $start_only) 1849 { 1850 mtr_error("--wait-all can only be used with --start options"); 1851 } 1852 1853 # -------------------------------------------------------------------------- 1854 # Gather stress-test options and modify behavior 1855 # -------------------------------------------------------------------------- 1856 1857 if ($opt_stress) 1858 { 1859 $opt_stress=~ s/,/ /g; 1860 $opt_user_args= 1; 1861 mtr_error("--stress cannot be combined with named ordinary suites or tests") 1862 if $opt_suites || @opt_cases; 1863 $opt_suites="stress"; 1864 @opt_cases= ("wrapper"); 1865 $ENV{MST_OPTIONS}= $opt_stress; 1866 $opt_ctest= 0; 1867 } 1868 1869 # -------------------------------------------------------------------------- 1870 # Check timeout arguments 1871 # -------------------------------------------------------------------------- 1872 1873 mtr_error("Invalid value '$opt_testcase_timeout' supplied ". 1874 "for option --testcase-timeout") 1875 if ($opt_testcase_timeout <= 0); 1876 mtr_error("Invalid value '$opt_suite_timeout' supplied ". 1877 "for option --testsuite-timeout") 1878 if ($opt_suite_timeout <= 0); 1879 1880 # -------------------------------------------------------------------------- 1881 # Check trace protocol option 1882 # -------------------------------------------------------------------------- 1883 if ( $opt_trace_protocol ) 1884 { 1885 push(@opt_extra_mysqld_opt, "--optimizer_trace=enabled=on,one_line=off"); 1886 # Some queries yield big traces: 1887 push(@opt_extra_mysqld_opt, "--optimizer-trace-max-mem-size=1000000"); 1888 } 1889 1890 # -------------------------------------------------------------------------- 1891 # Check valgrind arguments 1892 # -------------------------------------------------------------------------- 1893 if ( $opt_valgrind or $opt_valgrind_path or @valgrind_args) 1894 { 1895 mtr_report("Turning on valgrind for all executables"); 1896 $opt_valgrind= 1; 1897 $opt_valgrind_mysqld= 1; 1898 $opt_valgrind_mysqltest= 1; 1899 1900 # Increase the timeouts when running with valgrind 1901 $opt_testcase_timeout*= 10; 1902 $opt_suite_timeout*= 6; 1903 $opt_start_timeout*= 10; 1904 $opt_debug_sync_timeout*= 10; 1905 } 1906 elsif ( $opt_valgrind_mysqld ) 1907 { 1908 mtr_report("Turning on valgrind for mysqld(s) only"); 1909 $opt_valgrind= 1; 1910 } 1911 elsif ( $opt_valgrind_mysqltest ) 1912 { 1913 mtr_report("Turning on valgrind for mysqltest and mysql_client_test only"); 1914 $opt_valgrind= 1; 1915 } 1916 1917 if ( $opt_helgrind ) 1918 { 1919 mtr_report("Turning on valgrind with helgrind for mysqld(s)"); 1920 $opt_valgrind= 1; 1921 $opt_valgrind_mysqld= 1; 1922 1923 push(@valgrind_args, "--tool=helgrind"); 1924 } 1925 1926 if ( $opt_callgrind ) 1927 { 1928 mtr_report("Turning on valgrind with callgrind for mysqld(s)"); 1929 $opt_valgrind= 1; 1930 $opt_valgrind_mysqld= 1; 1931 1932 push(@valgrind_args, "--tool=callgrind", "--trace-children=yes"); 1933 1934 # Increase the timeouts when running with callgrind 1935 $opt_testcase_timeout*= 10; 1936 $opt_suite_timeout*= 6; 1937 $opt_start_timeout*= 10; 1938 $opt_debug_sync_timeout*= 10; 1939 } 1940 1941 if ($opt_valgrind) 1942 { 1943 # Default to --tool=memcheck if no other tool has been explicitly 1944 # specified. From >= 2.1.2, this option is needed 1945 if (!@valgrind_args or !grep(/^--tool=/, @valgrind_args)) 1946 { 1947 # Set default valgrind options for memcheck, can be overriden by user 1948 unshift(@valgrind_args, ("--tool=memcheck", "--num-callers=16", 1949 "--show-reachable=yes")); 1950 } 1951 1952 # Add suppression file if not specified 1953 if (!grep(/^--suppressions=/, @valgrind_args)) 1954 { 1955 push(@valgrind_args,"--suppressions=${glob_mysql_test_dir}/valgrind.supp") 1956 if -f "$glob_mysql_test_dir/valgrind.supp"; 1957 } 1958 1959 # Don't add --quiet; you will loose the summary reports. 1960 mtr_report("Running valgrind with options \"", 1961 join(" ", @valgrind_args), "\""); 1962 1963 # Turn off check testcases to save time 1964 mtr_report("Turning off --check-testcases to save time when valgrinding"); 1965 $opt_check_testcases = 0; 1966 } 1967 1968 if ($opt_debug_common) 1969 { 1970 $opt_debug= 1; 1971 $debug_d= "d,query,info,error,enter,exit"; 1972 } 1973 1974 if ( $opt_strace_server && ($^O ne "linux") ) 1975 { 1976 $opt_strace_server=0; 1977 mtr_warning("Strace only supported in Linux "); 1978 } 1979 1980 if ( $opt_strace_client && ($^O ne "linux") ) 1981 { 1982 $opt_strace_client=0; 1983 mtr_warning("Strace only supported in Linux "); 1984 } 1985 1986 1987 mtr_report("Checking supported features..."); 1988 1989 check_ndbcluster_support(\%mysqld_variables); 1990 check_ssl_support(\%mysqld_variables); 1991 check_debug_support(\%mysqld_variables); 1992 1993 executable_setup(); 1994 1995} 1996 1997 1998# 1999# To make it easier for different devs to work on the same host, 2000# an environment variable can be used to control all ports. A small 2001# number is to be used, 0 - 16 or similar. 2002# 2003# Note the MASTER_MYPORT has to be set the same in all 4.x and 5.x 2004# versions of this script, else a 4.0 test run might conflict with a 2005# 5.1 test run, even if different MTR_BUILD_THREAD is used. This means 2006# all port numbers might not be used in this version of the script. 2007# 2008# Also note the limitation of ports we are allowed to hand out. This 2009# differs between operating systems and configuration, see 2010# http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html 2011# But a fairly safe range seems to be 5001 - 32767 2012# 2013sub set_build_thread_ports($) { 2014 my $thread= shift || 0; 2015 2016 if ( lc($opt_build_thread) eq 'auto' ) { 2017 my $found_free = 0; 2018 $build_thread = 300; # Start attempts from here 2019 2020 my $build_thread_upper = $build_thread + ($opt_parallel > 39 2021 ? $opt_parallel + int($opt_parallel / 4) 2022 : 49); 2023 while (! $found_free) 2024 { 2025 $build_thread= mtr_get_unique_id($build_thread, $build_thread_upper); 2026 if ( !defined $build_thread ) { 2027 mtr_error("Could not get a unique build thread id"); 2028 } 2029 $found_free= check_ports_free($build_thread); 2030 # If not free, release and try from next number 2031 if (! $found_free) { 2032 mtr_release_unique_id(); 2033 $build_thread++; 2034 } 2035 } 2036 } 2037 else 2038 { 2039 $build_thread = $opt_build_thread + $thread - 1; 2040 if (! check_ports_free($build_thread)) { 2041 # Some port was not free(which one has already been printed) 2042 mtr_error("Some port(s) was not free") 2043 } 2044 } 2045 $ENV{MTR_BUILD_THREAD}= $build_thread; 2046 2047 # Calculate baseport 2048 $baseport= $build_thread * 10 + 10000; 2049 if ( $baseport < 5001 or $baseport + 9 >= 32767 ) 2050 { 2051 mtr_error("MTR_BUILD_THREAD number results in a port", 2052 "outside 5001 - 32767", 2053 "($baseport - $baseport + 9)"); 2054 } 2055 2056 mtr_report("Using MTR_BUILD_THREAD $build_thread,", 2057 "with reserved ports $baseport..".($baseport+9)); 2058 2059} 2060 2061 2062sub collect_mysqld_features { 2063 my $found_variable_list_start= 0; 2064 my $use_tmpdir; 2065 if ( defined $opt_tmpdir and -d $opt_tmpdir){ 2066 # Create the tempdir in $opt_tmpdir 2067 $use_tmpdir= $opt_tmpdir; 2068 } 2069 my $tmpdir= tempdir(CLEANUP => 0, # Directory removed by this function 2070 DIR => $use_tmpdir); 2071 2072 # 2073 # Execute "mysqld --no-defaults --help --verbose" to get a 2074 # list of all features and settings 2075 # 2076 # --no-defaults and --skip-grant-tables are to avoid loading 2077 # system-wide configs and plugins 2078 # 2079 # --datadir must exist, mysqld will chdir into it 2080 # 2081 my $args; 2082 mtr_init_args(\$args); 2083 mtr_add_arg($args, "--no-defaults"); 2084 mtr_add_arg($args, "--basedir=%s", $basedir); 2085 mtr_add_arg($args, "--datadir=%s", mixed_path($tmpdir)); 2086 mtr_add_arg($args, "--secure-file-priv=\"\""); 2087 mtr_add_arg($args, "--lc-messages-dir=%s", $path_language); 2088 mtr_add_arg($args, "--skip-grant-tables"); 2089 mtr_add_arg($args, "--verbose"); 2090 mtr_add_arg($args, "--help"); 2091 2092 # Need --user=root if running as *nix root user 2093 if (!IS_WINDOWS and $> == 0) 2094 { 2095 mtr_add_arg($args, "--user=root"); 2096 } 2097 2098 foreach my $extra_opt (@opt_extra_mysqld_opt) { 2099 if ($extra_opt =~ /--plugin-load/) { 2100 mtr_add_arg($args, $extra_opt); 2101 } 2102 } 2103 2104 my $exe_mysqld= find_mysqld($basedir); 2105 my $cmd= join(" ", $exe_mysqld, @$args); 2106 my $list= `$cmd`; 2107 2108 foreach my $line (split('\n', $list)) 2109 { 2110 # First look for version 2111 if ( !$mysql_version_id ) 2112 { 2113 # Look for version 2114 my $exe_name= basename($exe_mysqld); 2115 mtr_verbose("exe_name: $exe_name"); 2116 if ( $line =~ /^\S*$exe_name\s\sVer\s([0-9]*)\.([0-9]*)\.([0-9]*)([^\s]*)/ ) 2117 { 2118 #print "Major: $1 Minor: $2 Build: $3\n"; 2119 $mysql_version_id= $1*10000 + $2*100 + $3; 2120 #print "mysql_version_id: $mysql_version_id\n"; 2121 mtr_report("MySQL Version $1.$2.$3"); 2122 $mysql_version_extra= $4; 2123 } 2124 } 2125 else 2126 { 2127 if (!$found_variable_list_start) 2128 { 2129 # Look for start of variables list 2130 if ( $line =~ /[\-]+\s[\-]+/ ) 2131 { 2132 $found_variable_list_start= 1; 2133 } 2134 } 2135 else 2136 { 2137 # Put variables into hash 2138 if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ ) 2139 { 2140 # print "$1=\"$2\"\n"; 2141 $mysqld_variables{$1}= $2; 2142 } 2143 else 2144 { 2145 # The variable list is ended with a blank line 2146 if ( $line =~ /^[\s]*$/ ) 2147 { 2148 last; 2149 } 2150 else 2151 { 2152 # Send out a warning, we should fix the variables that has no 2153 # space between variable name and it's value 2154 # or should it be fixed width column parsing? It does not 2155 # look like that in function my_print_variables in my_getopt.c 2156 mtr_warning("Could not parse variable list line : $line"); 2157 } 2158 } 2159 } 2160 } 2161 } 2162 rmtree($tmpdir); 2163 mtr_error("Could not find version of MySQL") unless $mysql_version_id; 2164 mtr_error("Could not find variabes list") unless $found_variable_list_start; 2165 2166} 2167 2168 2169 2170sub collect_mysqld_features_from_running_server () 2171{ 2172 my $mysql= mtr_exe_exists("$path_client_bindir/mysql"); 2173 2174 my $args; 2175 mtr_init_args(\$args); 2176 2177 mtr_add_arg($args, "--no-defaults"); 2178 mtr_add_arg($args, "--user=%s", $opt_user); 2179 2180 while (my ($option, $value)= each( %opts_extern )) { 2181 mtr_add_arg($args, "--$option=$value"); 2182 } 2183 2184 mtr_add_arg($args, "--silent"); # Tab separated output 2185 mtr_add_arg($args, "-e '%s'", "use mysql; SHOW VARIABLES"); 2186 my $cmd= "$mysql " . join(' ', @$args); 2187 mtr_verbose("cmd: $cmd"); 2188 2189 my $list = `$cmd` or 2190 mtr_error("Could not connect to extern server using command: '$cmd'"); 2191 foreach my $line (split('\n', $list )) 2192 { 2193 # Put variables into hash 2194 if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ ) 2195 { 2196 # print "$1=\"$2\"\n"; 2197 $mysqld_variables{$1}= $2; 2198 } 2199 } 2200 2201 # "Convert" innodb flag 2202 $mysqld_variables{'innodb'}= "ON" 2203 if ($mysqld_variables{'have_innodb'} eq "YES"); 2204 2205 # Parse version 2206 my $version_str= $mysqld_variables{'version'}; 2207 if ( $version_str =~ /^([0-9]*)\.([0-9]*)\.([0-9]*)([^\s]*)/ ) 2208 { 2209 #print "Major: $1 Minor: $2 Build: $3\n"; 2210 $mysql_version_id= $1*10000 + $2*100 + $3; 2211 #print "mysql_version_id: $mysql_version_id\n"; 2212 mtr_report("MySQL Version $1.$2.$3"); 2213 $mysql_version_extra= $4; 2214 } 2215 mtr_error("Could not find version of MySQL") unless $mysql_version_id; 2216} 2217 2218sub find_mysqld { 2219 2220 my ($mysqld_basedir)= $ENV{MTR_BINDIR}|| @_; 2221 2222 my @mysqld_names= ("mysqld", "mysqld-max-nt", "mysqld-max", 2223 "mysqld-nt"); 2224 2225 if ( $opt_debug_server ){ 2226 # Put mysqld-debug first in the list of binaries to look for 2227 mtr_verbose("Adding mysqld-debug first in list of binaries to look for"); 2228 unshift(@mysqld_names, "mysqld-debug"); 2229 } 2230 2231 return my_find_bin($mysqld_basedir, 2232 ["sql", "libexec", "sbin", "bin"], 2233 [@mysqld_names]); 2234} 2235 2236 2237sub executable_setup () { 2238 2239 # 2240 # Check if libtool is available in this distribution/clone 2241 # we need it when valgrinding or debugging non installed binary 2242 # Otherwise valgrind will valgrind the libtool wrapper or bash 2243 # and gdb will not find the real executable to debug 2244 # 2245 if ( -x "../libtool") 2246 { 2247 $exe_libtool= "../libtool"; 2248 if ($opt_valgrind or $glob_debugger) 2249 { 2250 mtr_report("Using \"$exe_libtool\" when running valgrind or debugger"); 2251 } 2252 } 2253 2254 # Look for the client binaries 2255 $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); 2256 $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); 2257 $exe_mysql_plugin= mtr_exe_exists("$path_client_bindir/mysql_plugin"); 2258 2259 $exe_mysql_embedded= 2260 mtr_exe_maybe_exists(vs_config_dirs('libmysqld/examples','mysql_embedded'), 2261 "$bindir/libmysqld/examples/mysql_embedded", 2262 "$bindir/bin/mysql_embedded"); 2263 2264 if ( $ndbcluster_enabled ) 2265 { 2266 # Look for single threaded NDB 2267 $exe_ndbd= 2268 my_find_bin($bindir, 2269 ["storage/ndb/src/kernel", "libexec", "sbin", "bin"], 2270 "ndbd"); 2271 2272 # Look for multi threaded NDB 2273 $exe_ndbmtd= 2274 my_find_bin($bindir, 2275 ["storage/ndb/src/kernel", "libexec", "sbin", "bin"], 2276 "ndbmtd", NOT_REQUIRED); 2277 if ($exe_ndbmtd) 2278 { 2279 my $mtr_ndbmtd = $ENV{MTR_NDBMTD}; 2280 if ($mtr_ndbmtd) 2281 { 2282 mtr_report(" - multi threaded ndbd found, will be used always"); 2283 $exe_ndbd = $exe_ndbmtd; 2284 } 2285 else 2286 { 2287 mtr_report(" - multi threaded ndbd found, will be ". 2288 "used \"round robin\""); 2289 } 2290 } 2291 2292 $exe_ndb_mgmd= 2293 my_find_bin($bindir, 2294 ["storage/ndb/src/mgmsrv", "libexec", "sbin", "bin"], 2295 "ndb_mgmd"); 2296 2297 $exe_ndb_mgm= 2298 my_find_bin($bindir, 2299 ["storage/ndb/src/mgmclient", "bin"], 2300 "ndb_mgm"); 2301 2302 $exe_ndb_waiter= 2303 my_find_bin($bindir, 2304 ["storage/ndb/tools/", "bin"], 2305 "ndb_waiter"); 2306 2307 } 2308 2309 # Look for mysqltest executable 2310 if ( $opt_embedded_server ) 2311 { 2312 $exe_mysqltest= 2313 mtr_exe_exists(vs_config_dirs('libmysqld/examples','mysqltest_embedded'), 2314 "$basedir/libmysqld/examples/mysqltest_embedded", 2315 "$path_client_bindir/mysqltest_embedded"); 2316 } 2317 else 2318 { 2319 if ( defined $ENV{'MYSQL_TEST'} ) 2320 { 2321 $exe_mysqltest=$ENV{'MYSQL_TEST'}; 2322 print "===========================================================\n"; 2323 print "WARNING:The mysqltest binary is fetched from $exe_mysqltest\n"; 2324 print "===========================================================\n"; 2325 } 2326 else 2327 { 2328 $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); 2329 } 2330 } 2331 2332} 2333 2334 2335sub client_debug_arg($$) { 2336 my ($args, $client_name)= @_; 2337 2338 # Workaround for Bug #50627: drop any debug opt 2339 return if $client_name =~ /^mysqlbinlog/; 2340 2341 if ( $opt_debug ) { 2342 mtr_add_arg($args, 2343 "--loose-debug=$debug_d:t:A,%s/log/%s.trace", 2344 $path_vardir_trace, $client_name) 2345 } 2346} 2347 2348 2349sub client_arguments ($;$) { 2350 my $client_name= shift; 2351 my $group_suffix= shift; 2352 my $client_exe= mtr_exe_exists("$path_client_bindir/$client_name"); 2353 2354 my $args; 2355 mtr_init_args(\$args); 2356 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 2357 if (defined($group_suffix)) { 2358 mtr_add_arg($args, "--defaults-group-suffix=%s", $group_suffix); 2359 client_debug_arg($args, "$client_name-$group_suffix"); 2360 } 2361 else 2362 { 2363 client_debug_arg($args, $client_name); 2364 } 2365 return mtr_args2str($client_exe, @$args); 2366} 2367 2368sub client_arguments_no_grp_suffix($) { 2369 my $client_name= shift; 2370 my $client_exe= mtr_exe_exists("$path_client_bindir/$client_name"); 2371 my $args; 2372 2373 return mtr_args2str($client_exe, @$args); 2374} 2375 2376 2377sub mysqlslap_arguments () { 2378 my $exe= mtr_exe_maybe_exists("$path_client_bindir/mysqlslap"); 2379 if ( $exe eq "" ) { 2380 # mysqlap was not found 2381 2382 if (defined $mysql_version_id and $mysql_version_id >= 50100 ) { 2383 mtr_error("Could not find the mysqlslap binary"); 2384 } 2385 return ""; # Don't care about mysqlslap 2386 } 2387 2388 my $args; 2389 mtr_init_args(\$args); 2390 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 2391 client_debug_arg($args, "mysqlslap"); 2392 return mtr_args2str($exe, @$args); 2393} 2394 2395 2396sub mysqldump_arguments ($) { 2397 my($group_suffix) = @_; 2398 my $exe= mtr_exe_exists("$path_client_bindir/mysqldump"); 2399 2400 my $args; 2401 mtr_init_args(\$args); 2402 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 2403 mtr_add_arg($args, "--defaults-group-suffix=%s", $group_suffix); 2404 client_debug_arg($args, "mysqldump-$group_suffix"); 2405 return mtr_args2str($exe, @$args); 2406} 2407 2408 2409sub mysql_client_test_arguments(){ 2410 my $exe; 2411 # mysql_client_test executable may _not_ exist 2412 $exe= mtr_exe_maybe_exists(vs_config_dirs('tests', 'mysql_client_test'), 2413 "$basedir/tests/mysql_client_test", 2414 "$basedir/bin/mysql_client_test"); 2415 return "" unless $exe; 2416 my $args; 2417 mtr_init_args(\$args); 2418 if ( $opt_valgrind_mysqltest ) { 2419 valgrind_arguments($args, \$exe); 2420 } 2421 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 2422 mtr_add_arg($args, "--testcase"); 2423 mtr_add_arg($args, "--vardir=$opt_vardir"); 2424 client_debug_arg($args,"mysql_client_test"); 2425 2426 return mtr_args2str($exe, @$args); 2427} 2428 2429 2430# 2431# Set environment to be used by childs of this process for 2432# things that are constant during the whole lifetime of mysql-test-run 2433# 2434 2435sub find_plugin($$) 2436{ 2437 my ($plugin, $location) = @_; 2438 my $plugin_filename; 2439 2440 if (IS_WINDOWS) 2441 { 2442 $plugin_filename = $plugin.".dll"; 2443 } 2444 else 2445 { 2446 $plugin_filename = $plugin.".so"; 2447 } 2448 2449 my $lib_plugin= 2450 mtr_file_exists(vs_config_dirs($location,$plugin_filename), 2451 "$basedir/lib/plugin/".$plugin_filename, 2452 "$basedir/lib64/plugin/".$plugin_filename, 2453 "$basedir/$location/.libs/".$plugin_filename, 2454 "$basedir/lib/mysql/plugin/".$plugin_filename, 2455 "$basedir/lib64/mysql/plugin/".$plugin_filename, 2456 ); 2457 return $lib_plugin; 2458} 2459 2460# 2461# Read plugin defintions file 2462# 2463 2464sub read_plugin_defs($) 2465{ 2466 my ($defs_file)= @_; 2467 my $running_debug= 0; 2468 2469 open(PLUGDEF, '<', $defs_file) 2470 or mtr_error("Can't read plugin defintions file $defs_file"); 2471 2472 # Need to check if we will be running mysqld-debug 2473 if ($opt_debug_server) { 2474 $running_debug= 1 if find_mysqld($basedir) =~ /mysqld-debug/; 2475 } 2476 2477 while (<PLUGDEF>) { 2478 next if /^#/; 2479 my ($plug_file, $plug_loc, $plug_var, $plug_names)= split; 2480 # Allow empty lines 2481 next unless $plug_file; 2482 mtr_error("Lines in $defs_file must have 3 or 4 items") unless $plug_var; 2483 2484 # If running debug server, plugins will be in 'debug' subdirectory 2485 $plug_file= "debug/$plug_file" if $running_debug && !$source_dist; 2486 2487 my ($plugin)= find_plugin($plug_file, $plug_loc); 2488 2489 # Set env. variables that tests may use, set to empty if plugin 2490 # listed in def. file but not found. 2491 2492 if ($plugin) { 2493 my $plug_dir= dirname($plugin); 2494 $ENV{$plug_var}= basename($plugin); 2495 $ENV{$plug_var.'_DIR'}= $plug_dir; 2496 $ENV{$plug_var.'_OPT'}= "--plugin-dir=".$plug_dir; 2497 if ($plug_names) { 2498 my $lib_name= basename($plugin); 2499 my $load_var= "--plugin_load="; 2500 my $load_add_var= "--plugin_load_add="; 2501 my $load_var_with_path = "--plugin_load="; 2502 my $load_add_var_with_path = "--plugin_load_add="; 2503 my $semi= ''; 2504 foreach my $plug_name (split (',', $plug_names)) { 2505 $load_var .= $semi . "$plug_name=$lib_name"; 2506 $load_add_var .= $semi . "$plug_name=$lib_name"; 2507 $load_var_with_path .= $semi . "$plug_name=$plug_dir/$lib_name"; 2508 $load_add_var_with_path .= $semi . "$plug_name=$plug_dir/$lib_name"; 2509 $semi= ';'; 2510 } 2511 $ENV{$plug_var.'_LOAD'}= $load_var; 2512 $ENV{$plug_var.'_LOAD_ADD'}= $load_add_var; 2513 $ENV{$plug_var.'_LOAD_PATH'}= $load_var_with_path; 2514 $ENV{$plug_var.'_LOAD_ADD_PATH'}= $load_add_var_with_path; 2515 } 2516 } else { 2517 $ENV{$plug_var}= ""; 2518 $ENV{$plug_var.'_DIR'}= ""; 2519 $ENV{$plug_var.'_OPT'}= ""; 2520 $ENV{$plug_var.'_LOAD'}= "" if $plug_names; 2521 $ENV{$plug_var.'_LOAD_ADD'}= "" if $plug_names; 2522 $ENV{$plug_var.'_LOAD_PATH'}= "" if $plug_names; 2523 $ENV{$plug_var.'_LOAD_ADD_PATH'}= "" if $plug_names; 2524 } 2525 } 2526 close PLUGDEF; 2527} 2528 2529sub environment_setup { 2530 2531 umask(022); 2532 2533 my @ld_library_paths; 2534 2535 if ($path_client_libdir) 2536 { 2537 # Use the --client-libdir passed on commandline 2538 push(@ld_library_paths, "$path_client_libdir"); 2539 } 2540 else 2541 { 2542 # Setup LD_LIBRARY_PATH so the libraries from this distro/clone 2543 # are used in favor of the system installed ones 2544 if ( $source_dist ) 2545 { 2546 push(@ld_library_paths, "$basedir/libmysql/.libs/", 2547 "$basedir/libmysql_r/.libs/", 2548 "$basedir/zlib/.libs/"); 2549 } 2550 else 2551 { 2552 push(@ld_library_paths, "$basedir/lib", "$basedir/lib/mysql"); 2553 } 2554 } 2555 2556 # -------------------------------------------------------------------------- 2557 # Add the path where libndbclient can be found 2558 # -------------------------------------------------------------------------- 2559 if ( $ndbcluster_enabled ) 2560 { 2561 push(@ld_library_paths, 2562 "$basedir/storage/ndb/src/.libs", 2563 "$basedir/storage/ndb/src"); 2564 } 2565 2566 # Plugin settings should no longer be added here, instead 2567 # place definitions in include/plugin.defs. 2568 # See comment in that file for details. 2569 # -------------------------------------------------------------------------- 2570 # Valgrind need to be run with debug libraries otherwise it's almost 2571 # impossible to add correct supressions, that means if "/usr/lib/debug" 2572 # is available, it should be added to 2573 # LD_LIBRARY_PATH 2574 # 2575 # But pthread is broken in libc6-dbg on Debian <= 3.1 (see Debian 2576 # bug 399035, http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=399035), 2577 # so don't change LD_LIBRARY_PATH on that platform. 2578 # -------------------------------------------------------------------------- 2579 my $debug_libraries_path= "/usr/lib/debug"; 2580 my $deb_version; 2581 if ( $opt_valgrind and -d $debug_libraries_path and 2582 (! -e '/etc/debian_version' or 2583 ($deb_version= 2584 mtr_grab_file('/etc/debian_version')) !~ /^[0-9]+\.[0-9]$/ or 2585 $deb_version > 3.1 ) ) 2586 { 2587 push(@ld_library_paths, $debug_libraries_path); 2588 } 2589 2590 $ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths, 2591 $ENV{'LD_LIBRARY_PATH'} ? 2592 split(':', $ENV{'LD_LIBRARY_PATH'}) : ()); 2593 mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}"); 2594 2595 $ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths, 2596 $ENV{'DYLD_LIBRARY_PATH'} ? 2597 split(':', $ENV{'DYLD_LIBRARY_PATH'}) : ()); 2598 mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}"); 2599 2600 # The environment variable used for shared libs on AIX 2601 $ENV{'SHLIB_PATH'}= join(":", @ld_library_paths, 2602 $ENV{'SHLIB_PATH'} ? 2603 split(':', $ENV{'SHLIB_PATH'}) : ()); 2604 mtr_debug("SHLIB_PATH: $ENV{'SHLIB_PATH'}"); 2605 2606 # The environment variable used for shared libs on hp-ux 2607 $ENV{'LIBPATH'}= join(":", @ld_library_paths, 2608 $ENV{'LIBPATH'} ? 2609 split(':', $ENV{'LIBPATH'}) : ()); 2610 mtr_debug("LIBPATH: $ENV{'LIBPATH'}"); 2611 2612 $ENV{'UMASK'}= "0660"; # The octal *string* 2613 $ENV{'UMASK_DIR'}= "0770"; # The octal *string* 2614 2615 # 2616 # MySQL tests can produce output in various character sets 2617 # (especially, ctype_xxx.test). To avoid confusing Perl 2618 # with output which is incompatible with the current locale 2619 # settings, we reset the current values of LC_ALL and LC_CTYPE to "C". 2620 # For details, please see 2621 # Bug#27636 tests fails if LC_* variables set to *_*.UTF-8 2622 # 2623 $ENV{'LC_ALL'}= "C"; 2624 $ENV{'LC_CTYPE'}= "C"; 2625 2626 $ENV{'LC_COLLATE'}= "C"; 2627 $ENV{'USE_RUNNING_SERVER'}= using_extern(); 2628 $ENV{'MYSQL_TEST_DIR'}= $glob_mysql_test_dir; 2629 $ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'port'}; 2630 $ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir; 2631 $ENV{'MYSQLTEST_VARDIR'}= $opt_vardir; 2632 $ENV{'MYSQL_TEST_DIR_ABS'}= getcwd(); 2633 $ENV{'MYSQL_BINDIR'}= "$bindir"; 2634 $ENV{'MYSQL_SHAREDIR'}= $path_language; 2635 $ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir; 2636 2637 if (IS_WINDOWS) 2638 { 2639 $ENV{'SECURE_LOAD_PATH'}= $glob_mysql_test_dir."\\std_data"; 2640 $ENV{'MYSQL_TEST_LOGIN_FILE'}= $opt_tmpdir . "\\.mylogin.cnf"; 2641 $ENV{'MYSQLTEST_VARDIR_ABS'}= $opt_vardir; 2642 } 2643 else 2644 { 2645 $ENV{'SECURE_LOAD_PATH'}= $glob_mysql_test_dir."/std_data"; 2646 $ENV{'MYSQL_TEST_LOGIN_FILE'}= $opt_tmpdir . "/.mylogin.cnf"; 2647 $ENV{'MYSQLTEST_VARDIR_ABS'}= abs_path("$opt_vardir"); 2648 } 2649 2650 2651 # ---------------------------------------------------- 2652 # Setup env for NDB 2653 # ---------------------------------------------------- 2654 if ( $ndbcluster_enabled ) 2655 { 2656 $ENV{'NDB_MGM'}= 2657 my_find_bin($bindir, 2658 ["storage/ndb/src/mgmclient", "bin"], 2659 "ndb_mgm"); 2660 2661 $ENV{'NDB_WAITER'}= $exe_ndb_waiter; 2662 2663 $ENV{'NDB_RESTORE'}= 2664 my_find_bin($bindir, 2665 ["storage/ndb/tools", "bin"], 2666 "ndb_restore"); 2667 2668 $ENV{'NDB_CONFIG'}= 2669 my_find_bin($bindir, 2670 ["storage/ndb/tools", "bin"], 2671 "ndb_config"); 2672 2673 $ENV{'NDB_SELECT_ALL'}= 2674 my_find_bin($bindir, 2675 ["storage/ndb/tools", "bin"], 2676 "ndb_select_all"); 2677 2678 $ENV{'NDB_DROP_TABLE'}= 2679 my_find_bin($bindir, 2680 ["storage/ndb/tools", "bin"], 2681 "ndb_drop_table"); 2682 2683 $ENV{'NDB_DESC'}= 2684 my_find_bin($bindir, 2685 ["storage/ndb/tools", "bin"], 2686 "ndb_desc"); 2687 2688 $ENV{'NDB_SHOW_TABLES'}= 2689 my_find_bin($bindir, 2690 ["storage/ndb/tools", "bin"], 2691 "ndb_show_tables"); 2692 2693 $ENV{'NDB_EXAMPLES_DIR'}= 2694 my_find_dir($basedir, 2695 ["storage/ndb/ndbapi-examples", "bin"]); 2696 2697 $ENV{'NDB_EXAMPLES_BINARY'}= 2698 my_find_bin($bindir, 2699 ["storage/ndb/ndbapi-examples/ndbapi_simple", "bin"], 2700 "ndbapi_simple", NOT_REQUIRED); 2701 2702 my $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log"; 2703 $ENV{'NDB_TOOLS_OUTPUT'}= $path_ndb_testrun_log; 2704 $ENV{'NDB_EXAMPLES_OUTPUT'}= $path_ndb_testrun_log; 2705 } 2706 2707 # ---------------------------------------------------- 2708 # mysql clients 2709 # ---------------------------------------------------- 2710 $ENV{'MYSQL_CHECK'}= client_arguments("mysqlcheck"); 2711 $ENV{'MYSQL_DUMP'}= mysqldump_arguments(".1"); 2712 $ENV{'MYSQL_DUMP_SLAVE'}= mysqldump_arguments(".2"); 2713 $ENV{'MYSQL_SLAP'}= mysqlslap_arguments(); 2714 $ENV{'MYSQL_IMPORT'}= client_arguments("mysqlimport"); 2715 $ENV{'MYSQL_SHOW'}= client_arguments("mysqlshow"); 2716 $ENV{'MYSQL_CONFIG_EDITOR'}= client_arguments_no_grp_suffix("mysql_config_editor"); 2717 $ENV{'MYSQL_BINLOG'}= client_arguments("mysqlbinlog"); 2718 $ENV{'MYSQL'}= client_arguments("mysql"); 2719 $ENV{'MYSQL_SLAVE'}= client_arguments("mysql", ".2"); 2720 $ENV{'MYSQL_UPGRADE'}= client_arguments("mysql_upgrade"); 2721 $ENV{'MYSQLADMIN'}= native_path($exe_mysqladmin); 2722 $ENV{'MYSQL_CLIENT_TEST'}= mysql_client_test_arguments(); 2723 $ENV{'EXE_MYSQL'}= $exe_mysql; 2724 $ENV{'MYSQL_PLUGIN'}= $exe_mysql_plugin; 2725 $ENV{'MYSQL_EMBEDDED'}= $exe_mysql_embedded; 2726 $ENV{'PATH_CONFIG_FILE'}= $path_config_file; 2727 2728 my $exe_mysqld= find_mysqld($basedir); 2729 $ENV{'MYSQLD'}= $exe_mysqld; 2730 my $extra_opts= join (" ", @opt_extra_mysqld_opt); 2731 $ENV{'MYSQLD_CMD'}= "$exe_mysqld --defaults-group-suffix=.1 ". 2732 "--defaults-file=$path_config_file $extra_opts"; 2733 2734 # ---------------------------------------------------- 2735 # bug25714 executable may _not_ exist in 2736 # some versions, test using it should be skipped 2737 # ---------------------------------------------------- 2738 my $exe_bug25714= 2739 mtr_exe_maybe_exists(vs_config_dirs('tests', 'bug25714'), 2740 "$basedir/tests/bug25714"); 2741 $ENV{'MYSQL_BUG25714'}= native_path($exe_bug25714); 2742 2743 # ---------------------------------------------------- 2744 # Get the bin dir 2745 # ---------------------------------------------------- 2746 $ENV{'MYSQL_BIN_PATH'}= native_path($bindir); 2747 2748 # ---------------------------------------------------- 2749 # mysql_fix_privilege_tables.sql 2750 # ---------------------------------------------------- 2751 my $file_mysql_fix_privilege_tables= 2752 mtr_file_exists("$basedir/scripts/mysql_fix_privilege_tables.sql", 2753 "$basedir/share/mysql_fix_privilege_tables.sql", 2754 "$basedir/share/mysql/mysql_fix_privilege_tables.sql", 2755 "$bindir/scripts/mysql_fix_privilege_tables.sql", 2756 "$bindir/share/mysql_fix_privilege_tables.sql", 2757 "$bindir/share/mysql/mysql_fix_privilege_tables.sql"); 2758 $ENV{'MYSQL_FIX_PRIVILEGE_TABLES'}= $file_mysql_fix_privilege_tables; 2759 2760 # ---------------------------------------------------- 2761 # my_print_defaults 2762 # ---------------------------------------------------- 2763 my $exe_my_print_defaults= 2764 mtr_exe_exists(vs_config_dirs('extra', 'my_print_defaults'), 2765 "$path_client_bindir/my_print_defaults", 2766 "$basedir/extra/my_print_defaults"); 2767 $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= native_path($exe_my_print_defaults); 2768 2769 # ---------------------------------------------------- 2770 # Setup env so childs can execute innochecksum 2771 # ---------------------------------------------------- 2772 my $exe_innochecksum= 2773 mtr_exe_exists(vs_config_dirs('extra', 'innochecksum'), 2774 "$path_client_bindir/innochecksum", 2775 "$basedir/extra/innochecksum"); 2776 $ENV{'INNOCHECKSUM'}= native_path($exe_innochecksum); 2777 2778 # ---------------------------------------------------- 2779 # sst_dump 2780 # ---------------------------------------------------- 2781 my $exe_sst_dump= 2782 mtr_exe_maybe_exists( 2783 vs_config_dirs('storage/rocksdb', 'sst_dump'), 2784 "$path_client_bindir/sst_dump", 2785 "$basedir/storage/rocksdb/sst_dump"); 2786 $ENV{'MYSQL_SST_DUMP'}= native_path($exe_sst_dump); 2787 2788 # ---------------------------------------------------- 2789 # tokuft_dump 2790 # ---------------------------------------------------- 2791 my $exe_tokuftdump= 2792 mtr_exe_maybe_exists( 2793 vs_config_dirs('storage/tokudb/PerconaFT/tools', 'tokuftdump'), 2794 "$path_client_bindir/tokuftdump", 2795 "$basedir/storage/tokudb/PerconaFT/tools/tokuftdump"); 2796 $ENV{'MYSQL_TOKUFTDUMP'}= native_path($exe_tokuftdump); 2797 2798 2799 # ---------------------------------------------------- 2800 # Setup env so childs can execute myisampack and myisamchk 2801 # ---------------------------------------------------- 2802 $ENV{'MYISAMCHK'}= native_path(mtr_exe_exists( 2803 vs_config_dirs('storage/myisam', 'myisamchk'), 2804 vs_config_dirs('myisam', 'myisamchk'), 2805 "$path_client_bindir/myisamchk", 2806 "$basedir/storage/myisam/myisamchk", 2807 "$basedir/myisam/myisamchk")); 2808 $ENV{'MYISAMPACK'}= native_path(mtr_exe_exists( 2809 vs_config_dirs('storage/myisam', 'myisampack'), 2810 vs_config_dirs('myisam', 'myisampack'), 2811 "$path_client_bindir/myisampack", 2812 "$basedir/storage/myisam/myisampack", 2813 "$basedir/myisam/myisampack")); 2814 2815 # ---------------------------------------------------- 2816 # mysqlaccess 2817 # ---------------------------------------------------- 2818 my $mysqlaccess= 2819 mtr_pl_maybe_exists("$bindir/scripts/mysqlaccess") || 2820 mtr_pl_maybe_exists("$path_client_bindir/mysqlaccess"); 2821 if ($mysqlaccess) 2822 { 2823 $ENV{'MYSQLACCESS'}= $mysqlaccess; 2824 } 2825 2826 # ---------------------------------------------------- 2827 # mysqlhotcopy 2828 # ---------------------------------------------------- 2829 my $mysqlhotcopy= 2830 mtr_pl_maybe_exists("$bindir/scripts/mysqlhotcopy") || 2831 mtr_pl_maybe_exists("$path_client_bindir/mysqlhotcopy"); 2832 if ($mysqlhotcopy) 2833 { 2834 $ENV{'MYSQLHOTCOPY'}= $mysqlhotcopy; 2835 } 2836 2837 # ---------------------------------------------------- 2838 # perror 2839 # ---------------------------------------------------- 2840 my $exe_perror= mtr_exe_exists(vs_config_dirs('extra', 'perror'), 2841 "$basedir/extra/perror", 2842 "$path_client_bindir/perror"); 2843 $ENV{'MY_PERROR'}= native_path($exe_perror); 2844 2845 # ---------------------------------------------------- 2846 # replace 2847 # ---------------------------------------------------- 2848 my $exe_replace= mtr_exe_exists(vs_config_dirs('extra', 'replace'), 2849 "$basedir/extra/replace", 2850 "$path_client_bindir/replace"); 2851 $ENV{'REPLACE'}= native_path($exe_replace); 2852 2853 # Create an environment variable to make it possible 2854 # to detect that valgrind is being used from test cases 2855 $ENV{'VALGRIND_TEST'}= $opt_valgrind; 2856 2857 # Add dir of this perl to aid mysqltest in finding perl 2858 my $perldir= dirname($^X); 2859 my $pathsep= ":"; 2860 $pathsep= ";" if IS_WINDOWS && ! IS_CYGWIN; 2861 $ENV{'PATH'}= "$ENV{'PATH'}".$pathsep.$perldir; 2862} 2863 2864 2865sub remove_vardir_subs() { 2866 foreach my $sdir ( glob("$opt_vardir/*") ) { 2867 mtr_verbose("Removing subdir $sdir"); 2868 rmtree($sdir); 2869 } 2870} 2871 2872# 2873# Remove var and any directories in var/ created by previous 2874# tests 2875# 2876sub remove_stale_vardir () { 2877 2878 mtr_report("Removing old var directory..."); 2879 2880 # Safety! 2881 mtr_error("No, don't remove the vardir when running with --extern") 2882 if using_extern(); 2883 2884 mtr_verbose("opt_vardir: $opt_vardir"); 2885 if ( $opt_vardir eq $default_vardir ) 2886 { 2887 # 2888 # Running with "var" in mysql-test dir 2889 # 2890 if ( -l $opt_vardir) 2891 { 2892 # var is a symlink 2893 2894 if ( $opt_mem ) 2895 { 2896 # Remove the directory which the link points at 2897 mtr_verbose("Removing " . readlink($opt_vardir)); 2898 rmtree(readlink($opt_vardir)); 2899 2900 # Remove the "var" symlink 2901 mtr_verbose("unlink($opt_vardir)"); 2902 unlink($opt_vardir); 2903 } 2904 else 2905 { 2906 # Some users creates a soft link in mysql-test/var to another area 2907 # - allow it, but remove all files in it 2908 2909 mtr_report(" - WARNING: Using the 'mysql-test/var' symlink"); 2910 2911 # Make sure the directory where it points exist 2912 mtr_error("The destination for symlink $opt_vardir does not exist") 2913 if ! -d readlink($opt_vardir); 2914 2915 remove_vardir_subs(); 2916 } 2917 } 2918 else 2919 { 2920 # Remove the entire "var" dir 2921 mtr_verbose("Removing $opt_vardir/"); 2922 rmtree("$opt_vardir/"); 2923 } 2924 2925 if ( $opt_mem ) 2926 { 2927 # A symlink from var/ to $opt_mem will be set up 2928 # remove the $opt_mem dir to assure the symlink 2929 # won't point at an old directory 2930 mtr_verbose("Removing $opt_mem"); 2931 rmtree($opt_mem); 2932 } 2933 2934 } 2935 else 2936 { 2937 # 2938 # Running with "var" in some other place 2939 # 2940 2941 # Remove the var/ dir in mysql-test dir if any 2942 # this could be an old symlink that shouldn't be there 2943 mtr_verbose("Removing $default_vardir"); 2944 rmtree($default_vardir); 2945 2946 # Remove the "var" dir 2947 mtr_verbose("Removing $opt_vardir/"); 2948 rmtree("$opt_vardir/"); 2949 } 2950 # Remove the "tmp" dir 2951 mtr_verbose("Removing $opt_tmpdir/"); 2952 rmtree("$opt_tmpdir/"); 2953} 2954 2955 2956 2957# 2958# Create var and the directories needed in var 2959# 2960sub setup_vardir() { 2961 mtr_report("Creating var directory '$opt_vardir'..."); 2962 2963 if ( $opt_vardir eq $default_vardir ) 2964 { 2965 # 2966 # Running with "var" in mysql-test dir 2967 # 2968 if ( -l $opt_vardir ) 2969 { 2970 # it's a symlink 2971 2972 # Make sure the directory where it points exist 2973 mtr_error("The destination for symlink $opt_vardir does not exist") 2974 if ! -d readlink($opt_vardir); 2975 } 2976 elsif ( $opt_mem ) 2977 { 2978 # Runinng with "var" as a link to some "memory" location, normally tmpfs 2979 mtr_verbose("Creating $opt_mem"); 2980 mkpath($opt_mem); 2981 2982 mtr_report(" - symlinking 'var' to '$opt_mem'"); 2983 symlink($opt_mem, $opt_vardir); 2984 } 2985 } 2986 2987 if ( ! -d $opt_vardir ) 2988 { 2989 mtr_verbose("Creating $opt_vardir"); 2990 mkpath($opt_vardir); 2991 } 2992 2993 # Ensure a proper error message if vardir couldn't be created 2994 unless ( -d $opt_vardir and -w $opt_vardir ) 2995 { 2996 mtr_error("Writable 'var' directory is needed, use the " . 2997 "'--vardir=<path>' option"); 2998 } 2999 3000 mkpath("$opt_vardir/log"); 3001 mkpath("$opt_vardir/run"); 3002 3003 # Create var/tmp and tmp - they might be different 3004 mkpath("$opt_vardir/tmp"); 3005 mkpath($opt_tmpdir) if ($opt_tmpdir ne "$opt_vardir/tmp"); 3006 3007 # On some operating systems, there is a limit to the length of a 3008 # UNIX domain socket's path far below PATH_MAX. 3009 # Don't allow that to happen 3010 if (check_socket_path_length("$opt_tmpdir/testsocket.sock")){ 3011 mtr_error("Socket path '$opt_tmpdir' too long, it would be ", 3012 "truncated and thus not possible to use for connection to ", 3013 "MySQL Server. Set a shorter with --tmpdir=<path> option"); 3014 } 3015 3016 # copy all files from std_data into var/std_data 3017 # and make them world readable 3018 copytree("$glob_mysql_test_dir/std_data", "$opt_vardir/std_data", "0022"); 3019 3020 # Remove old log files 3021 foreach my $name (glob("r/*.progress r/*.log r/*.warnings")) 3022 { 3023 unlink($name); 3024 } 3025} 3026 3027 3028# 3029# Check if running as root 3030# i.e a file can be read regardless what mode we set it to 3031# 3032sub check_running_as_root () { 3033 my $test_file= "$opt_vardir/test_running_as_root.txt"; 3034 mtr_tofile($test_file, "MySQL"); 3035 chmod(oct("0000"), $test_file); 3036 3037 my $result=""; 3038 if (open(FILE,"<",$test_file)) 3039 { 3040 $result= join('', <FILE>); 3041 close FILE; 3042 } 3043 3044 # Some filesystems( for example CIFS) allows reading a file 3045 # although mode was set to 0000, but in that case a stat on 3046 # the file will not return 0000 3047 my $file_mode= (stat($test_file))[2] & 07777; 3048 3049 mtr_verbose("result: $result, file_mode: $file_mode"); 3050 if ($result eq "MySQL" && $file_mode == 0) 3051 { 3052 mtr_warning("running this script as _root_ will cause some " . 3053 "tests to be skipped"); 3054 $ENV{'MYSQL_TEST_ROOT'}= "YES"; 3055 } 3056 3057 chmod(oct("0755"), $test_file); 3058 unlink($test_file); 3059} 3060 3061 3062sub check_ssl_support ($) { 3063 my $mysqld_variables= shift; 3064 3065 if ($opt_skip_ssl) 3066 { 3067 mtr_report(" - skipping SSL"); 3068 $opt_ssl_supported= 0; 3069 $opt_ssl= 0; 3070 return; 3071 } 3072 3073 if ( ! $mysqld_variables->{'ssl'} ) 3074 { 3075 if ( $opt_ssl) 3076 { 3077 mtr_error("Couldn't find support for SSL"); 3078 return; 3079 } 3080 mtr_report(" - skipping SSL, mysqld not compiled with SSL"); 3081 $opt_ssl_supported= 0; 3082 $opt_ssl= 0; 3083 return; 3084 } 3085 mtr_report(" - SSL connections supported"); 3086 $opt_ssl_supported= 1; 3087} 3088 3089 3090sub check_debug_support ($) { 3091 my $mysqld_variables= shift; 3092 3093 if ( ! $mysqld_variables->{'debug'} ) 3094 { 3095 #mtr_report(" - binaries are not debug compiled"); 3096 $debug_compiled_binaries= 0; 3097 3098 if ( $opt_debug ) 3099 { 3100 mtr_error("Can't use --debug, binary does not support it"); 3101 } 3102 if ( $opt_debug_server ) 3103 { 3104 mtr_warning("Ignoring --debug-server, binary does not support it"); 3105 } 3106 return; 3107 } 3108 mtr_report(" - binaries are debug compiled"); 3109 $debug_compiled_binaries= 1; 3110} 3111 3112 3113# 3114# Helper function to handle configuration-based subdirectories which Visual 3115# Studio uses for storing binaries. If opt_vs_config is set, this returns 3116# a path based on that setting; if not, it returns paths for the default 3117# /release/ and /debug/ subdirectories. 3118# 3119# $exe can be undefined, if the directory itself will be used 3120# 3121sub vs_config_dirs ($$) { 3122 my ($path_part, $exe) = @_; 3123 3124 $exe = "" if not defined $exe; 3125 if ($opt_vs_config) 3126 { 3127 return ("$bindir/$path_part/$opt_vs_config/$exe"); 3128 } 3129 3130 return ("$bindir/$path_part/Release/$exe", 3131 "$bindir/$path_part/RelWithDebinfo/$exe", 3132 "$bindir/$path_part/Debug/$exe", 3133 "$bindir/$path_part/$exe"); 3134} 3135 3136 3137sub check_ndbcluster_support ($) { 3138 my $mysqld_variables= shift; 3139 3140 my $ndbcluster_supported = 0; 3141 if ($mysqld_variables{'ndb-connectstring'}) 3142 { 3143 $ndbcluster_supported = 1; 3144 } 3145 3146 if ($opt_skip_ndbcluster && $opt_include_ndbcluster) 3147 { 3148 # User is ambivalent. Theoretically the arg which was 3149 # given last on command line should win, but that order is 3150 # unknown at this time. 3151 mtr_error("Ambigous command, both --include-ndbcluster " . 3152 " and --skip-ndbcluster was specified"); 3153 } 3154 3155 # Check if this is MySQL Cluster, ie. mysql version string ends 3156 # with -ndb-Y.Y.Y[-status] 3157 if ( defined $mysql_version_extra && 3158 $mysql_version_extra =~ /-ndb-([0-9]*)\.([0-9]*)\.([0-9]*)/ ) 3159 { 3160 # MySQL Cluster tree 3161 mtr_report(" - MySQL Cluster detected"); 3162 3163 if ($opt_skip_ndbcluster) 3164 { 3165 mtr_report(" - skipping ndbcluster(--skip-ndbcluster)"); 3166 return; 3167 } 3168 3169 if (!$ndbcluster_supported) 3170 { 3171 # MySQL Cluster tree, but mysqld was not compiled with 3172 # ndbcluster -> fail unless --skip-ndbcluster was used 3173 mtr_error("This is MySQL Cluster but mysqld does not " . 3174 "support ndbcluster. Use --skip-ndbcluster to " . 3175 "force mtr to run without it."); 3176 } 3177 3178 # mysqld was compiled with ndbcluster -> auto enable 3179 } 3180 else 3181 { 3182 # Not a MySQL Cluster tree 3183 if (!$ndbcluster_supported) 3184 { 3185 if ($opt_include_ndbcluster) 3186 { 3187 mtr_error("Could not detect ndbcluster support ". 3188 "requested with --include-ndbcluster"); 3189 } 3190 3191 # Silently skip, mysqld was compiled without ndbcluster 3192 # which is the default case 3193 return; 3194 } 3195 3196 if ($opt_skip_ndbcluster) 3197 { 3198 # Compiled with ndbcluster but ndbcluster skipped 3199 mtr_report(" - skipping ndbcluster(--skip-ndbcluster)"); 3200 return; 3201 } 3202 3203 3204 # Not a MySQL Cluster tree, enable ndbcluster 3205 # if --include-ndbcluster was used 3206 if ($opt_include_ndbcluster) 3207 { 3208 # enable ndbcluster 3209 } 3210 else 3211 { 3212 mtr_report(" - skipping ndbcluster(disabled by default)"); 3213 return; 3214 } 3215 } 3216 3217 mtr_report(" - enabling ndbcluster"); 3218 $ndbcluster_enabled= 1; 3219 # Add MySQL Cluster test suites 3220 $DEFAULT_SUITES.=",ndb,ndb_binlog,rpl_ndb,ndb_rpl,ndb_memcache"; 3221 return; 3222} 3223 3224 3225sub ndbcluster_wait_started($$){ 3226 my $cluster= shift; 3227 my $ndb_waiter_extra_opt= shift; 3228 my $path_waitlog= join('/', $opt_vardir, $cluster->name(), "ndb_waiter.log"); 3229 3230 my $args; 3231 mtr_init_args(\$args); 3232 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 3233 mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix()); 3234 mtr_add_arg($args, "--timeout=%d", $opt_start_timeout); 3235 3236 if ($ndb_waiter_extra_opt) 3237 { 3238 mtr_add_arg($args, "$ndb_waiter_extra_opt"); 3239 } 3240 3241 # Start the ndb_waiter which will connect to the ndb_mgmd 3242 # and poll it for state of the ndbd's, will return when 3243 # all nodes in the cluster is started 3244 3245 my $res= My::SafeProcess->run 3246 ( 3247 name => "ndb_waiter ".$cluster->name(), 3248 path => $exe_ndb_waiter, 3249 args => \$args, 3250 output => $path_waitlog, 3251 error => $path_waitlog, 3252 append => 1, 3253 ); 3254 3255 # Check that ndb_mgmd(s) are still alive 3256 foreach my $ndb_mgmd ( in_cluster($cluster, ndb_mgmds()) ) 3257 { 3258 my $proc= $ndb_mgmd->{proc}; 3259 if ( ! $proc->wait_one(0) ) 3260 { 3261 mtr_warning("$proc died"); 3262 return 2; 3263 } 3264 } 3265 3266 # Check that all started ndbd(s) are still alive 3267 foreach my $ndbd ( in_cluster($cluster, ndbds()) ) 3268 { 3269 my $proc= $ndbd->{proc}; 3270 next unless defined $proc; 3271 if ( ! $proc->wait_one(0) ) 3272 { 3273 mtr_warning("$proc died"); 3274 return 3; 3275 } 3276 } 3277 3278 if ($res) 3279 { 3280 mtr_verbose("ndbcluster_wait_started failed"); 3281 return 1; 3282 } 3283 return 0; 3284} 3285 3286 3287sub ndbcluster_dump($) { 3288 my ($cluster)= @_; 3289 3290 print "\n== Dumping cluster log files\n\n"; 3291 3292 # ndb_mgmd(s) 3293 foreach my $ndb_mgmd ( in_cluster($cluster, ndb_mgmds()) ) 3294 { 3295 my $datadir = $ndb_mgmd->value('DataDir'); 3296 3297 # Should find ndb_<nodeid>_cluster.log and ndb_mgmd.log 3298 foreach my $file ( glob("$datadir/ndb*.log") ) 3299 { 3300 print "$file:\n"; 3301 mtr_printfile("$file"); 3302 print "\n"; 3303 } 3304 } 3305 3306 # ndb(s) 3307 foreach my $ndbd ( in_cluster($cluster, ndbds()) ) 3308 { 3309 my $datadir = $ndbd->value('DataDir'); 3310 3311 # Should find ndbd.log 3312 foreach my $file ( glob("$datadir/ndbd.log") ) 3313 { 3314 print "$file:\n"; 3315 mtr_printfile("$file"); 3316 print "\n"; 3317 } 3318 } 3319} 3320 3321 3322sub ndb_mgmd_wait_started($) { 3323 my ($cluster)= @_; 3324 3325 my $retries= 100; 3326 while ($retries) 3327 { 3328 my $result= ndbcluster_wait_started($cluster, "--no-contact"); 3329 if ($result == 0) 3330 { 3331 # ndb_mgmd is started 3332 mtr_verbose("ndb_mgmd is started"); 3333 return 0; 3334 } 3335 elsif ($result > 1) 3336 { 3337 mtr_warning("Cluster process failed while waiting for start"); 3338 return $result; 3339 } 3340 3341 mtr_milli_sleep(100); 3342 $retries--; 3343 } 3344 3345 return 1; 3346} 3347 3348sub ndb_mgmd_stop{ 3349 my $ndb_mgmd= shift or die "usage: ndb_mgmd_stop(<ndb_mgmd>)"; 3350 3351 my $host=$ndb_mgmd->value('HostName'); 3352 my $port=$ndb_mgmd->value('PortNumber'); 3353 mtr_verbose("Stopping cluster '$host:$port'"); 3354 3355 my $args; 3356 mtr_init_args(\$args); 3357 mtr_add_arg($args, "--ndb-connectstring=%s:%s", $host,$port); 3358 mtr_add_arg($args, "-e"); 3359 mtr_add_arg($args, "shutdown"); 3360 3361 My::SafeProcess->run 3362 ( 3363 name => "ndb_mgm shutdown $host:$port", 3364 path => $exe_ndb_mgm, 3365 args => \$args, 3366 output => "/dev/null", 3367 ); 3368} 3369 3370sub ndb_mgmd_start ($$) { 3371 my ($cluster, $ndb_mgmd)= @_; 3372 3373 mtr_verbose("ndb_mgmd_start"); 3374 3375 my $dir= $ndb_mgmd->value("DataDir"); 3376 mkpath($dir) unless -d $dir; 3377 3378 my $args; 3379 mtr_init_args(\$args); 3380 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 3381 mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix()); 3382 mtr_add_arg($args, "--mycnf"); 3383 mtr_add_arg($args, "--nodaemon"); 3384 mtr_add_arg($args, "--configdir=%s", "$dir"); 3385 3386 my $path_ndb_mgmd_log= "$dir/ndb_mgmd.log"; 3387 3388 $ndb_mgmd->{'proc'}= My::SafeProcess->new 3389 ( 3390 name => $ndb_mgmd->after('cluster_config.'), 3391 path => $exe_ndb_mgmd, 3392 args => \$args, 3393 output => $path_ndb_mgmd_log, 3394 error => $path_ndb_mgmd_log, 3395 append => 1, 3396 verbose => $opt_verbose, 3397 shutdown => sub { ndb_mgmd_stop($ndb_mgmd) }, 3398 ); 3399 mtr_verbose("Started $ndb_mgmd->{proc}"); 3400 3401 # FIXME Should not be needed 3402 # Unfortunately the cluster nodes will fail to start 3403 # if ndb_mgmd has not started properly 3404 if (ndb_mgmd_wait_started($cluster)) 3405 { 3406 mtr_warning("Failed to wait for start of ndb_mgmd"); 3407 return 1; 3408 } 3409 3410 return 0; 3411} 3412 3413sub ndbd_stop { 3414 # Intentionally left empty, ndbd nodes will be shutdown 3415 # by sending "shutdown" to ndb_mgmd 3416} 3417 3418my $exe_ndbmtd_counter= 0; 3419 3420sub ndbd_start { 3421 my ($cluster, $ndbd)= @_; 3422 3423 mtr_verbose("ndbd_start"); 3424 3425 my $dir= $ndbd->value("DataDir"); 3426 mkpath($dir) unless -d $dir; 3427 3428 my $args; 3429 mtr_init_args(\$args); 3430 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 3431 mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix()); 3432 mtr_add_arg($args, "--nodaemon"); 3433 3434# > 5.0 { 'character-sets-dir' => \&fix_charset_dir }, 3435 3436 my $exe= $exe_ndbd; 3437 if ($exe_ndbmtd) 3438 { if ($ENV{MTR_NDBMTD}) 3439 { 3440 # ndbmtd forced by env var MTR_NDBMTD 3441 $exe= $exe_ndbmtd; 3442 } 3443 if (($exe_ndbmtd_counter++ % 2) == 0) 3444 { 3445 # Use ndbmtd every other time 3446 $exe= $exe_ndbmtd; 3447 } 3448 } 3449 3450 my $path_ndbd_log= "$dir/ndbd.log"; 3451 my $proc= My::SafeProcess->new 3452 ( 3453 name => $ndbd->after('cluster_config.'), 3454 path => $exe, 3455 args => \$args, 3456 output => $path_ndbd_log, 3457 error => $path_ndbd_log, 3458 append => 1, 3459 verbose => $opt_verbose, 3460 shutdown => sub { ndbd_stop($ndbd) }, 3461 ); 3462 mtr_verbose("Started $proc"); 3463 3464 $ndbd->{proc}= $proc; 3465 3466 return; 3467} 3468 3469 3470sub memcached_start { 3471 my ($cluster, $memcached) = @_; 3472 3473 my $name = $memcached->name(); 3474 mtr_verbose("memcached_start '$name'"); 3475 3476 my $found_perl_source = my_find_file($basedir, 3477 ["storage/ndb/memcache", # source 3478 "mysql-test/lib", # install 3479 "share/mysql-test/lib"], # install 3480 "memcached_path.pl", NOT_REQUIRED); 3481 3482 mtr_verbose("Found memcache script: '$found_perl_source'"); 3483 $found_perl_source ne "" or return; 3484 3485 my $found_so = my_find_file($bindir, 3486 ["storage/ndb/memcache", # source or build 3487 "lib", "lib64"], # install 3488 "ndb_engine.so"); 3489 mtr_verbose("Found memcache plugin: '$found_so'"); 3490 3491 require "$found_perl_source"; 3492 if(! memcached_is_available()) 3493 { 3494 mtr_error("Memcached not available."); 3495 } 3496 my $exe = ""; 3497 if(memcached_is_bundled()) 3498 { 3499 $exe = my_find_bin($bindir, 3500 ["libexec", "sbin", "bin", "storage/ndb/memcache/extra/memcached"], 3501 "memcached", NOT_REQUIRED); 3502 } 3503 else 3504 { 3505 $exe = get_memcached_exe_path(); 3506 } 3507 $exe ne "" or mtr_error("Failed to find memcached."); 3508 3509 my $args; 3510 mtr_init_args(\$args); 3511 # TCP port number to listen on 3512 mtr_add_arg($args, "-p %d", $memcached->value('port')); 3513 # Max simultaneous connections 3514 mtr_add_arg($args, "-c %d", $memcached->value('max_connections')); 3515 # Load engine as storage engine, ie. /path/ndb_engine.so 3516 mtr_add_arg($args, "-E"); 3517 mtr_add_arg($args, $found_so); 3518 # Config options for loaded storage engine 3519 { 3520 my @opts; 3521 push(@opts, "connectstring=" . $memcached->value('ndb_connectstring')); 3522 push(@opts, $memcached->if_exist("options")); 3523 mtr_add_arg($args, "-e"); 3524 mtr_add_arg($args, join(";", @opts)); 3525 } 3526 3527 if($opt_gdb) 3528 { 3529 gdb_arguments(\$args, \$exe, "memcached"); 3530 } 3531 3532 my $proc = My::SafeProcess->new 3533 ( name => $name, 3534 path => $exe, 3535 args => \$args, 3536 output => "$opt_vardir/log/$name.out", 3537 error => "$opt_vardir/log/$name.out", 3538 append => 1, 3539 verbose => $opt_verbose, 3540 ); 3541 mtr_verbose("Started $proc"); 3542 3543 $memcached->{proc} = $proc; 3544 3545 return; 3546} 3547 3548 3549sub memcached_load_metadata($) { 3550 my $cluster= shift; 3551 3552 foreach my $mysqld (mysqlds()) 3553 { 3554 if(-d $mysqld->value('datadir') . "/" . "ndbmemcache") 3555 { 3556 mtr_verbose("skipping memcache metadata (already stored)"); 3557 return; 3558 } 3559 } 3560 3561 my $sql_script= my_find_file($bindir, 3562 ["share/mysql/memcache-api", # RPM install 3563 "share/memcache-api", # Other installs 3564 "scripts" # Build tree 3565 ], 3566 "ndb_memcache_metadata.sql", NOT_REQUIRED); 3567 mtr_verbose("memcached_load_metadata: '$sql_script'"); 3568 if (-f $sql_script ) 3569 { 3570 my $args; 3571 mtr_init_args(\$args); 3572 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 3573 mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix()); 3574 mtr_add_arg($args, "--connect-timeout=20"); 3575 if ( My::SafeProcess->run( 3576 name => "ndbmemcache config loader", 3577 path => $exe_mysql, 3578 args => \$args, 3579 input => $sql_script, 3580 output => "$opt_vardir/log/memcache_config.log", 3581 error => "$opt_vardir/log/memcache_config.log" 3582 ) != 0) 3583 { 3584 mtr_error("Could not load ndb_memcache_metadata.sql file"); 3585 } 3586 } 3587} 3588 3589 3590sub ndbcluster_start ($) { 3591 my $cluster= shift; 3592 3593 mtr_verbose("ndbcluster_start '".$cluster->name()."'"); 3594 3595 foreach my $ndb_mgmd ( in_cluster($cluster, ndb_mgmds()) ) 3596 { 3597 next if started($ndb_mgmd); 3598 ndb_mgmd_start($cluster, $ndb_mgmd); 3599 } 3600 3601 foreach my $ndbd ( in_cluster($cluster, ndbds()) ) 3602 { 3603 next if started($ndbd); 3604 ndbd_start($cluster, $ndbd); 3605 } 3606 3607 return 0; 3608} 3609 3610 3611sub create_config_file_for_extern { 3612 my %opts= 3613 ( 3614 socket => '/tmp/mysqld.sock', 3615 port => 3306, 3616 user => $opt_user, 3617 password => '', 3618 @_ 3619 ); 3620 3621 mtr_report("Creating my.cnf file for extern server..."); 3622 my $F= IO::File->new($path_config_file, "w") 3623 or mtr_error("Can't write to $path_config_file: $!"); 3624 3625 print $F "[client]\n"; 3626 while (my ($option, $value)= each( %opts )) { 3627 print $F "$option= $value\n"; 3628 mtr_report(" $option= $value"); 3629 } 3630 3631 print $F <<EOF 3632 3633# binlog reads from [client] and [mysqlbinlog] 3634[mysqlbinlog] 3635character-sets-dir= $path_charsetsdir 3636local-load= $opt_tmpdir 3637 3638EOF 3639; 3640 3641 $F= undef; # Close file 3642} 3643 3644 3645# 3646# Kill processes left from previous runs, normally 3647# there should be none so make sure to warn 3648# if there is one 3649# 3650sub kill_leftovers ($) { 3651 my $rundir= shift; 3652 return unless ( -d $rundir ); 3653 3654 mtr_report("Checking leftover processes..."); 3655 3656 # Scan the "run" directory for process id's to kill 3657 opendir(RUNDIR, $rundir) 3658 or mtr_error("kill_leftovers, can't open dir \"$rundir\": $!"); 3659 while ( my $elem= readdir(RUNDIR) ) 3660 { 3661 # Only read pid from files that end with .pid 3662 if ( $elem =~ /.*[.]pid$/ ) 3663 { 3664 my $pidfile= "$rundir/$elem"; 3665 next unless -f $pidfile; 3666 my $pid= mtr_fromfile($pidfile); 3667 unlink($pidfile); 3668 unless ($pid=~ /^(\d+)/){ 3669 # The pid was not a valid number 3670 mtr_warning("Got invalid pid '$pid' from '$elem'"); 3671 next; 3672 } 3673 mtr_report(" - found old pid $pid in '$elem', killing it..."); 3674 3675 my $ret= kill("KILL", $pid); 3676 if ($ret == 0) { 3677 mtr_report(" process did not exist!"); 3678 next; 3679 } 3680 3681 my $check_counter= 100; 3682 while ($ret > 0 and $check_counter--) { 3683 mtr_milli_sleep(100); 3684 $ret= kill(0, $pid); 3685 } 3686 mtr_report($check_counter ? " ok!" : " failed!"); 3687 } 3688 else 3689 { 3690 mtr_warning("Found non pid file '$elem' in '$rundir'") 3691 if -f "$rundir/$elem"; 3692 } 3693 } 3694 closedir(RUNDIR); 3695} 3696 3697# 3698# Check that all the ports that are going to 3699# be used are free 3700# 3701sub check_ports_free ($) 3702{ 3703 my $bthread= shift; 3704 my $portbase = $bthread * 10 + 10000; 3705 for ($portbase..$portbase+9){ 3706 if (mtr_ping_port($_)){ 3707 mtr_report(" - 'localhost:$_' was not free"); 3708 return 0; # One port was not free 3709 } 3710 } 3711 3712 return 1; # All ports free 3713} 3714 3715 3716sub initialize_servers { 3717 3718 if ( using_extern() ) 3719 { 3720 # Running against an already started server, if the specified 3721 # vardir does not already exist it should be created 3722 if ( ! -d $opt_vardir ) 3723 { 3724 setup_vardir(); 3725 } 3726 else 3727 { 3728 mtr_verbose("No need to create '$opt_vardir' it already exists"); 3729 } 3730 } 3731 else 3732 { 3733 # Kill leftovers from previous run 3734 # using any pidfiles found in var/run 3735 kill_leftovers("$opt_vardir/run"); 3736 3737 if ( ! $opt_start_dirty ) 3738 { 3739 remove_stale_vardir(); 3740 setup_vardir(); 3741 3742 mysql_install_db(default_mysqld(), "$opt_vardir/install.db"); 3743 } 3744 } 3745} 3746 3747 3748# 3749# Remove all newline characters expect after semicolon 3750# 3751sub sql_to_bootstrap { 3752 my ($sql) = @_; 3753 my @lines= split(/\n/, $sql); 3754 my $result= "\n"; 3755 my $delimiter= ';'; 3756 3757 foreach my $line (@lines) { 3758 3759 # Change current delimiter if line starts with "delimiter" 3760 if ( $line =~ /^delimiter (.*)/ ) { 3761 my $new= $1; 3762 # Remove old delimiter from end of new 3763 $new=~ s/\Q$delimiter\E$//; 3764 $delimiter = $new; 3765 mtr_debug("changed delimiter to $delimiter"); 3766 # No need to add the delimiter to result 3767 next; 3768 } 3769 3770 # Add newline if line ends with $delimiter 3771 # and convert the current delimiter to semicolon 3772 if ( $line =~ /\Q$delimiter\E$/ ){ 3773 $line =~ s/\Q$delimiter\E$/;/; 3774 $result.= "$line\n"; 3775 mtr_debug("Added default delimiter"); 3776 next; 3777 } 3778 3779 # Remove comments starting with -- 3780 if ( $line =~ /^\s*--/ ) { 3781 mtr_debug("Discarded $line"); 3782 next; 3783 } 3784 3785 # Replace @HOSTNAME with localhost 3786 $line=~ s/\'\@HOSTNAME\@\'/localhost/; 3787 3788 # Default, just add the line without newline 3789 # but with a space as separator 3790 $result.= "$line "; 3791 3792 } 3793 return $result; 3794} 3795 3796 3797sub default_mysqld { 3798 # Generate new config file from template 3799 my $config= My::ConfigFactory->new_config 3800 ( { 3801 basedir => $basedir, 3802 testdir => $glob_mysql_test_dir, 3803 template_path => "include/default_my.cnf", 3804 vardir => $opt_vardir, 3805 tmpdir => $opt_tmpdir, 3806 baseport => 0, 3807 user => $opt_user, 3808 password => '', 3809 } 3810 ); 3811 3812 my $mysqld= $config->group('mysqld.1') 3813 or mtr_error("Couldn't find mysqld.1 in default config"); 3814 return $mysqld; 3815} 3816 3817 3818sub mysql_install_db { 3819 my ($mysqld, $datadir)= @_; 3820 3821 my $install_datadir= $datadir || $mysqld->value('datadir'); 3822 my $install_basedir= $mysqld->value('basedir'); 3823 my $install_lang= $mysqld->value('lc-messages-dir'); 3824 my $install_chsdir= $mysqld->value('character-sets-dir'); 3825 3826 mtr_report("Installing system database..."); 3827 3828 my $args; 3829 mtr_init_args(\$args); 3830 mtr_add_arg($args, "--no-defaults"); 3831 mtr_add_arg($args, "--bootstrap"); 3832 mtr_add_arg($args, "--basedir=%s", $install_basedir); 3833 mtr_add_arg($args, "--datadir=%s", $install_datadir); 3834 mtr_add_arg($args, "--loose-skip-falcon"); 3835 mtr_add_arg($args, "--loose-skip-ndbcluster"); 3836 mtr_add_arg($args, "--tmpdir=%s", "$opt_vardir/tmp/"); 3837 mtr_add_arg($args, "--secure-file-priv=%s", "$opt_vardir"); 3838 mtr_add_arg($args, "--innodb-log-file-size=5M"); 3839 mtr_add_arg($args, "--core-file"); 3840 # over writing innodb_autoextend_increment to 8 for reducing the ibdata1 file size 3841 mtr_add_arg($args, "--innodb_autoextend_increment=8"); 3842 3843 if ( $opt_debug ) 3844 { 3845 mtr_add_arg($args, "--debug=$debug_d:t:i:A,%s/log/bootstrap.trace", 3846 $path_vardir_trace); 3847 } 3848 3849 mtr_add_arg($args, "--lc-messages-dir=%s", $install_lang); 3850 mtr_add_arg($args, "--character-sets-dir=%s", $install_chsdir); 3851 3852 # InnoDB arguments that affect file location and sizes may 3853 # need to be given to the bootstrap process as well as the 3854 # server process. 3855 foreach my $extra_opt ( @opt_extra_mysqld_opt ) { 3856 (my $temp_extra_opt=$extra_opt) =~ s/_/-/g; 3857 if ($temp_extra_opt =~ /--innodb-page-size/ || 3858 $temp_extra_opt =~ /--innodb-log-file-size/) { 3859 mtr_add_arg($args, $extra_opt); 3860 } 3861 } 3862 3863 # If DISABLE_GRANT_OPTIONS is defined when the server is compiled (e.g., 3864 # configure --disable-grant-options), mysqld will not recognize the 3865 # --bootstrap or --skip-grant-tables options. The user can set 3866 # MYSQLD_BOOTSTRAP to the full path to a mysqld which does accept 3867 # --bootstrap, to accommodate this. 3868 my $exe_mysqld_bootstrap = 3869 $ENV{'MYSQLD_BOOTSTRAP'} || find_mysqld($install_basedir); 3870 3871 # ---------------------------------------------------------------------- 3872 # export MYSQLD_BOOTSTRAP_CMD variable containing <path>/mysqld <args> 3873 # ---------------------------------------------------------------------- 3874 $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args); 3875 3876 3877 3878 # ---------------------------------------------------------------------- 3879 # Create the bootstrap.sql file 3880 # ---------------------------------------------------------------------- 3881 my $bootstrap_sql_file= "$opt_vardir/tmp/bootstrap.sql"; 3882 3883 if ($opt_boot_gdb) { 3884 gdb_arguments(\$args, \$exe_mysqld_bootstrap, $mysqld->name(), 3885 $bootstrap_sql_file); 3886 } 3887 if ($opt_boot_dbx) { 3888 dbx_arguments(\$args, \$exe_mysqld_bootstrap, $mysqld->name(), 3889 $bootstrap_sql_file); 3890 } 3891 if ($opt_boot_ddd) { 3892 ddd_arguments(\$args, \$exe_mysqld_bootstrap, $mysqld->name(), 3893 $bootstrap_sql_file); 3894 } 3895 3896 my $path_sql= my_find_file($install_basedir, 3897 ["mysql", "sql/share", "share/mysql", 3898 "share", "scripts"], 3899 "mysql_system_tables.sql", 3900 NOT_REQUIRED); 3901 3902 if (-f $path_sql ) 3903 { 3904 my $sql_dir= dirname($path_sql); 3905 # Use the mysql database for system tables 3906 mtr_tofile($bootstrap_sql_file, "use mysql;\n"); 3907 3908 # Add the offical mysql system tables 3909 # for a production system 3910 mtr_appendfile_to_file("$sql_dir/mysql_system_tables.sql", 3911 $bootstrap_sql_file); 3912 3913 # Add the mysql system tables initial data 3914 # for a production system 3915 mtr_appendfile_to_file("$sql_dir/mysql_system_tables_data.sql", 3916 $bootstrap_sql_file); 3917 3918 # Add test data for timezone - this is just a subset, on a real 3919 # system these tables will be populated either by mysql_tzinfo_to_sql 3920 # or by downloading the timezone table package from our website 3921 mtr_appendfile_to_file("$sql_dir/mysql_test_data_timezone.sql", 3922 $bootstrap_sql_file); 3923 3924 # Fill help tables, just an empty file when running from bk repo 3925 # but will be replaced by a real fill_help_tables.sql when 3926 # building the source dist 3927 mtr_appendfile_to_file("$sql_dir/fill_help_tables.sql", 3928 $bootstrap_sql_file); 3929 3930 } 3931 else 3932 { 3933 # Install db from init_db.sql that exist in early 5.1 and 5.0 3934 # versions of MySQL 3935 my $init_file= "$install_basedir/mysql-test/lib/init_db.sql"; 3936 mtr_report(" - from '$init_file'"); 3937 my $text= mtr_grab_file($init_file) or 3938 mtr_error("Can't open '$init_file': $!"); 3939 3940 mtr_tofile($bootstrap_sql_file, 3941 sql_to_bootstrap($text)); 3942 } 3943 3944 # Remove anonymous users 3945 mtr_tofile($bootstrap_sql_file, 3946 "DELETE FROM mysql.user where user= '';\n"); 3947 3948 # Create mtr database 3949 mtr_tofile($bootstrap_sql_file, 3950 "CREATE DATABASE mtr;\n"); 3951 3952 # Add help tables and data for warning detection and supression 3953 mtr_tofile($bootstrap_sql_file, 3954 sql_to_bootstrap(mtr_grab_file("include/mtr_warnings.sql"))); 3955 3956 # Add procedures for checking server is restored after testcase 3957 mtr_tofile($bootstrap_sql_file, 3958 sql_to_bootstrap(mtr_grab_file("include/mtr_check.sql"))); 3959 3960 # Log bootstrap command 3961 my $path_bootstrap_log= "$opt_vardir/log/bootstrap.log"; 3962 mtr_tofile($path_bootstrap_log, 3963 "$exe_mysqld_bootstrap " . join(" ", @$args) . "\n"); 3964 3965 # Create directories mysql and test 3966 mkpath("$install_datadir/mysql"); 3967 mkpath("$install_datadir/test"); 3968 3969 if ( My::SafeProcess->run 3970 ( 3971 name => "bootstrap", 3972 path => $exe_mysqld_bootstrap, 3973 args => \$args, 3974 input => $bootstrap_sql_file, 3975 output => $path_bootstrap_log, 3976 error => $path_bootstrap_log, 3977 append => 1, 3978 verbose => $opt_verbose, 3979 ) != 0) 3980 { 3981 mtr_error("Error executing mysqld --bootstrap\n" . 3982 "Could not install system database from $bootstrap_sql_file\n" . 3983 "see $path_bootstrap_log for errors"); 3984 } 3985} 3986 3987 3988sub run_testcase_check_skip_test($) 3989{ 3990 my ($tinfo)= @_; 3991 3992 # ---------------------------------------------------------------------- 3993 # If marked to skip, just print out and return. 3994 # Note that a test case not marked as 'skip' can still be 3995 # skipped later, because of the test case itself in cooperation 3996 # with the mysqltest program tells us so. 3997 # ---------------------------------------------------------------------- 3998 3999 if ( $tinfo->{'skip'} ) 4000 { 4001 mtr_report_test_skipped($tinfo) unless $start_only; 4002 return 1; 4003 } 4004 4005 return 0; 4006} 4007 4008 4009sub run_query { 4010 my ($tinfo, $mysqld, $query)= @_; 4011 4012 my $args; 4013 mtr_init_args(\$args); 4014 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 4015 mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld')); 4016 4017 mtr_add_arg($args, "-e %s", $query); 4018 4019 my $res= My::SafeProcess->run 4020 ( 4021 name => "run_query -> ".$mysqld->name(), 4022 path => $exe_mysql, 4023 args => \$args, 4024 output => '/dev/null', 4025 error => '/dev/null' 4026 ); 4027 4028 return $res 4029} 4030 4031 4032sub do_before_run_mysqltest($) 4033{ 4034 my $tinfo= shift; 4035 4036 $ENV{'MYSQL_CURRENT_TEST_DIR'} = dirname($tinfo->{'path'}); 4037 # Remove old files produced by mysqltest 4038 my $base_file= mtr_match_extension($tinfo->{result_file}, 4039 "result"); # Trim extension 4040 if (defined $base_file ){ 4041 unlink("$base_file.reject"); 4042 unlink("$base_file.progress"); 4043 unlink("$base_file.log"); 4044 unlink("$base_file.warnings"); 4045 } 4046 4047 if ( $mysql_version_id < 50000 ) { 4048 # Set environment variable NDB_STATUS_OK to 1 4049 # if script decided to run mysqltest cluster _is_ installed ok 4050 $ENV{'NDB_STATUS_OK'} = "1"; 4051 } elsif ( $mysql_version_id < 50100 ) { 4052 # Set environment variable NDB_STATUS_OK to YES 4053 # if script decided to run mysqltest cluster _is_ installed ok 4054 $ENV{'NDB_STATUS_OK'} = "YES"; 4055 } 4056} 4057 4058 4059# 4060# Check all server for sideffects 4061# 4062# RETURN VALUE 4063# 0 ok 4064# 1 Check failed 4065# >1 Fatal errro 4066 4067sub check_testcase($$) 4068{ 4069 my ($tinfo, $mode)= @_; 4070 my $tname= $tinfo->{name}; 4071 4072 # Start the mysqltest processes in parallel to save time 4073 # also makes it possible to wait for any process to exit during the check 4074 my %started; 4075 foreach my $mysqld ( mysqlds() ) 4076 { 4077 # Skip if server has been restarted with additional options 4078 if ( defined $mysqld->{'proc'} && ! exists $mysqld->{'restart_opts'} ) 4079 { 4080 my $proc= start_check_testcase($tinfo, $mode, $mysqld); 4081 $started{$proc->pid()}= $proc; 4082 } 4083 } 4084 4085 # Return immediately if no check proceess was started 4086 return 0 unless ( keys %started ); 4087 4088 my $timeout= start_timer(check_timeout($tinfo)); 4089 4090 while (1){ 4091 my $result; 4092 my $proc= My::SafeProcess->wait_any_timeout($timeout); 4093 mtr_report("Got $proc"); 4094 4095 if ( delete $started{$proc->pid()} ) { 4096 4097 my $err_file= $proc->user_data(); 4098 my $base_file= mtr_match_extension($err_file, "err"); # Trim extension 4099 4100 # One check testcase process returned 4101 my $res= $proc->exit_status(); 4102 4103 if ( $res == 0){ 4104 # Check completed without problem 4105 4106 # Remove the .err file the check generated 4107 unlink($err_file); 4108 4109 # Remove the .result file the check generated 4110 if ( $mode eq 'after' ){ 4111 unlink("$base_file.result"); 4112 } 4113 4114 if ( keys(%started) == 0){ 4115 # All checks completed 4116 mark_time_used('check'); 4117 return 0; 4118 } 4119 # Wait for next process to exit 4120 next; 4121 } 4122 else 4123 { 4124 if ( $mode eq "after" and $res == 1 ) 4125 { 4126 # Test failed, grab the report mysqltest has created 4127 my $report= mtr_grab_file($err_file); 4128 $tinfo->{check}.= 4129 "\nMTR's internal check of the test case '$tname' failed. 4130This means that the test case does not preserve the state that existed 4131before the test case was executed. Most likely the test case did not 4132do a proper clean-up. It could also be caused by the previous test run 4133by this thread, if the server wasn't restarted. 4134This is the diff of the states of the servers before and after the 4135test case was executed:\n"; 4136 $tinfo->{check}.= $report; 4137 4138 # Check failed, mark the test case with that info 4139 $tinfo->{'check_testcase_failed'}= 1; 4140 $result= 1; 4141 } 4142 elsif ( $res ) 4143 { 4144 my $report= mtr_grab_file($err_file); 4145 $tinfo->{comment}.= 4146 "Could not execute 'check-testcase' $mode ". 4147 "testcase '$tname' (res: $res):\n"; 4148 $tinfo->{comment}.= $report; 4149 4150 $result= 2; 4151 } 4152 4153 # Remove the .result file the check generated 4154 unlink("$base_file.result"); 4155 4156 } 4157 } 4158 elsif ( $proc->{timeout} ) { 4159 $tinfo->{comment}.= "Timeout for 'check-testcase' expired after " 4160 .check_timeout($tinfo)." seconds"; 4161 $result= 4; 4162 } 4163 else { 4164 # Unknown process returned, most likley a crash, abort everything 4165 $tinfo->{comment}= 4166 "The server $proc crashed while running ". 4167 "'check testcase $mode test'". 4168 get_log_from_proc($proc, $tinfo->{name}); 4169 $result= 3; 4170 } 4171 4172 # Kill any check processes still running 4173 map($_->kill(), values(%started)); 4174 4175 mtr_warning("Check-testcase failed, this could also be caused by the" . 4176 " previous test run by this worker thread") 4177 if $result > 1 && $mode eq "before"; 4178 mark_time_used('check'); 4179 4180 return $result; 4181 } 4182 4183 mtr_error("INTERNAL_ERROR: check_testcase"); 4184} 4185 4186 4187# Start run mysqltest on one server 4188# 4189# RETURN VALUE 4190# 0 OK 4191# 1 Check failed 4192# 4193sub start_run_one ($$) { 4194 my ($mysqld, $run)= @_; 4195 4196 my $name= "$run-".$mysqld->name(); 4197 4198 my $args; 4199 mtr_init_args(\$args); 4200 4201 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 4202 mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld')); 4203 4204 mtr_add_arg($args, "--silent"); 4205 mtr_add_arg($args, "--test-file=%s", "include/$run.test"); 4206 4207 my $errfile= "$opt_vardir/tmp/$name.err"; 4208 my $proc= My::SafeProcess->new 4209 ( 4210 name => $name, 4211 path => $exe_mysqltest, 4212 error => $errfile, 4213 output => $errfile, 4214 args => \$args, 4215 user_data => $errfile, 4216 verbose => $opt_verbose, 4217 ); 4218 mtr_verbose("Started $proc"); 4219 return $proc; 4220} 4221 4222 4223# 4224# Run script on all servers, collect results 4225# 4226# RETURN VALUE 4227# 0 ok 4228# 1 Failure 4229 4230sub run_on_all($$) 4231{ 4232 my ($tinfo, $run)= @_; 4233 4234 # Start the mysqltest processes in parallel to save time 4235 # also makes it possible to wait for any process to exit during the check 4236 # and to have a timeout process 4237 my %started; 4238 foreach my $mysqld ( mysqlds() ) 4239 { 4240 if ( defined $mysqld->{'proc'} ) 4241 { 4242 my $proc= start_run_one($mysqld, $run); 4243 $started{$proc->pid()}= $proc; 4244 } 4245 } 4246 4247 # Return immediately if no check proceess was started 4248 return 0 unless ( keys %started ); 4249 4250 my $timeout= start_timer(check_timeout($tinfo)); 4251 4252 while (1){ 4253 my $result; 4254 my $proc= My::SafeProcess->wait_any_timeout($timeout); 4255 mtr_report("Got $proc"); 4256 4257 if ( delete $started{$proc->pid()} ) { 4258 4259 # One mysqltest process returned 4260 my $err_file= $proc->user_data(); 4261 my $res= $proc->exit_status(); 4262 4263 # Append the report from .err file 4264 $tinfo->{comment}.= " == $err_file ==\n"; 4265 $tinfo->{comment}.= mtr_grab_file($err_file); 4266 $tinfo->{comment}.= "\n"; 4267 4268 # Remove the .err file 4269 unlink($err_file); 4270 4271 if ( keys(%started) == 0){ 4272 # All completed 4273 return 0; 4274 } 4275 4276 # Wait for next process to exit 4277 next; 4278 } 4279 elsif ($proc->{timeout}) { 4280 $tinfo->{comment}.= "Timeout for '$run' expired after " 4281 .check_timeout($tinfo)." seconds"; 4282 } 4283 else { 4284 # Unknown process returned, most likley a crash, abort everything 4285 $tinfo->{comment}.= 4286 "The server $proc crashed while running '$run'". 4287 get_log_from_proc($proc, $tinfo->{name}); 4288 } 4289 4290 # Kill any check processes still running 4291 map($_->kill(), values(%started)); 4292 4293 return 1; 4294 } 4295 mtr_error("INTERNAL_ERROR: run_on_all"); 4296} 4297 4298 4299sub mark_log { 4300 my ($log, $tinfo)= @_; 4301 my $log_msg= "CURRENT_TEST: $tinfo->{name}\n"; 4302 mtr_tofile($log, $log_msg); 4303} 4304 4305 4306sub find_testcase_skipped_reason($) 4307{ 4308 my ($tinfo)= @_; 4309 4310 # Set default message 4311 $tinfo->{'comment'}= "Detected by testcase(no log file)"; 4312 4313 # Open the test log file 4314 my $F= IO::File->new($path_current_testlog) 4315 or return; 4316 my $reason; 4317 4318 while ( my $line= <$F> ) 4319 { 4320 # Look for "reason: <reason for skipping test>" 4321 if ( $line =~ /reason: (.*)/ ) 4322 { 4323 $reason= $1; 4324 } 4325 } 4326 4327 if ( ! $reason ) 4328 { 4329 mtr_warning("Could not find reason for skipping test in $path_current_testlog"); 4330 $reason= "Detected by testcase(reason unknown) "; 4331 } 4332 $tinfo->{'comment'}= $reason; 4333} 4334 4335 4336sub find_analyze_request 4337{ 4338 # Open the test log file 4339 my $F= IO::File->new($path_current_testlog) 4340 or return; 4341 my $analyze; 4342 4343 while ( my $line= <$F> ) 4344 { 4345 # Look for "reason: <reason for skipping test>" 4346 if ( $line =~ /analyze: (.*)/ ) 4347 { 4348 $analyze= $1; 4349 } 4350 } 4351 4352 return $analyze; 4353} 4354 4355 4356# The test can leave a file in var/tmp/ to signal 4357# that all servers should be restarted 4358sub restart_forced_by_test($) 4359{ 4360 my $file = shift; 4361 my $restart = 0; 4362 foreach my $mysqld ( mysqlds() ) 4363 { 4364 my $datadir = $mysqld->value('datadir'); 4365 my $force_restart_file = "$datadir/mtr/$file"; 4366 if ( -f $force_restart_file ) 4367 { 4368 mtr_verbose("Restart of servers forced by test"); 4369 $restart = 1; 4370 last; 4371 } 4372 } 4373 return $restart; 4374} 4375 4376 4377# Return timezone value of tinfo or default value 4378sub timezone { 4379 my ($tinfo)= @_; 4380 return $tinfo->{timezone} || "GMT-3"; 4381} 4382 4383 4384# Storage for changed environment variables 4385my %old_env; 4386 4387sub resfile_report_test ($) { 4388 my $tinfo= shift; 4389 4390 resfile_new_test(); 4391 4392 resfile_test_info("name", $tinfo->{name}); 4393 resfile_test_info("variation", $tinfo->{combination}) 4394 if $tinfo->{combination}; 4395 resfile_test_info("start_time", isotime time); 4396} 4397 4398sub error_logs_to_comment { 4399 my $tinfo= shift; 4400 foreach my $mysqld (mysqlds()) 4401 { 4402 $tinfo->{comment}.= "\nServer " . $mysqld->{proc} . " log: ". 4403 get_log_from_proc($mysqld->{proc}, $tinfo->{name}); 4404 } 4405} 4406 4407# 4408# Run a single test case 4409# 4410# RETURN VALUE 4411# 0 OK 4412# > 0 failure 4413# 4414 4415sub run_testcase ($) { 4416 my $tinfo= shift; 4417 4418 my $print_freq=20; 4419 4420 mtr_verbose("Running test:", $tinfo->{name}); 4421 resfile_report_test($tinfo) if $opt_resfile; 4422 4423 # Allow only alpanumerics pluss _ - + . in combination names, 4424 # or anything beginning with -- (the latter comes from --combination) 4425 my $combination= $tinfo->{combination}; 4426 if ($combination && $combination !~ /^\w[-\w\.\+]+$/ 4427 && $combination !~ /^--/) 4428 { 4429 mtr_error("Combination '$combination' contains illegal characters"); 4430 } 4431 # ------------------------------------------------------- 4432 # Init variables that can change between each test case 4433 # ------------------------------------------------------- 4434 my $timezone= timezone($tinfo); 4435 $ENV{'TZ'}= $timezone; 4436 mtr_verbose("Setting timezone: $timezone"); 4437 4438 if ( ! using_extern() ) 4439 { 4440 my @restart= servers_need_restart($tinfo); 4441 if ( @restart != 0) { 4442 stop_servers($tinfo, @restart ); 4443 } 4444 4445 if ( started(all_servers()) == 0 ) 4446 { 4447 4448 # Remove old datadirs 4449 clean_datadir() unless $opt_start_dirty; 4450 4451 # Restore old ENV 4452 while (my ($option, $value)= each( %old_env )) { 4453 if (defined $value){ 4454 mtr_verbose("Restoring $option to $value"); 4455 $ENV{$option}= $value; 4456 4457 } else { 4458 mtr_verbose("Removing $option"); 4459 delete($ENV{$option}); 4460 } 4461 } 4462 %old_env= (); 4463 4464 mtr_verbose("Generating my.cnf from '$tinfo->{template_path}'"); 4465 4466 # Generate new config file from template 4467 $config= My::ConfigFactory->new_config 4468 ( { 4469 basedir => $basedir, 4470 testdir => $glob_mysql_test_dir, 4471 template_path => $tinfo->{template_path}, 4472 extra_template_path => $tinfo->{extra_template_path}, 4473 vardir => $opt_vardir, 4474 tmpdir => $opt_tmpdir, 4475 baseport => $baseport, 4476 #hosts => [ 'host1', 'host2' ], 4477 user => $opt_user, 4478 password => '', 4479 ssl => $opt_ssl_supported, 4480 embedded => $opt_embedded_server, 4481 } 4482 ); 4483 4484 # Write the new my.cnf 4485 $config->save($path_config_file); 4486 4487 # Remember current config so a restart can occur when a test need 4488 # to use a different one 4489 $current_config_name= $tinfo->{template_path}; 4490 4491 # 4492 # Set variables in the ENV section 4493 # 4494 foreach my $option ($config->options_in_group("ENV")) 4495 { 4496 # Save old value to restore it before next time 4497 $old_env{$option->name()}= $ENV{$option->name()}; 4498 4499 mtr_verbose($option->name(), "=",$option->value()); 4500 $ENV{$option->name()}= $option->value(); 4501 } 4502 } 4503 4504 # Write start of testcase to log 4505 mark_log($path_current_testlog, $tinfo); 4506 4507 if (start_servers($tinfo)) 4508 { 4509 report_failure_and_restart($tinfo); 4510 return 1; 4511 } 4512 } 4513 mark_time_used('restart'); 4514 4515 # -------------------------------------------------------------------- 4516 # If --start or --start-dirty given, stop here to let user manually 4517 # run tests 4518 # If --wait-all is also given, do the same, but don't die if one 4519 # server exits 4520 # ---------------------------------------------------------------------- 4521 4522 if ( $start_only ) 4523 { 4524 mtr_print("\nStarted", started(all_servers())); 4525 mtr_print("Using config for test", $tinfo->{name}); 4526 mtr_print("Port and socket path for server(s):"); 4527 foreach my $mysqld ( mysqlds() ) 4528 { 4529 mtr_print ($mysqld->name() . " " . $mysqld->value('port') . 4530 " " . $mysqld->value('socket')); 4531 } 4532 if ( $opt_start_exit ) 4533 { 4534 mtr_print("Server(s) started, not waiting for them to finish"); 4535 if (IS_WINDOWS) 4536 { 4537 POSIX::_exit(0); # exit hangs here in ActiveState Perl 4538 } 4539 else 4540 { 4541 exit(0); 4542 } 4543 } 4544 mtr_print("Waiting for server(s) to exit..."); 4545 if ( $opt_wait_all ) { 4546 My::SafeProcess->wait_all(); 4547 mtr_print( "All servers exited" ); 4548 exit(1); 4549 } 4550 else { 4551 my $proc= My::SafeProcess->wait_any(); 4552 if ( grep($proc eq $_, started(all_servers())) ) 4553 { 4554 mtr_print("Server $proc died"); 4555 exit(1); 4556 } 4557 mtr_print("Unknown process $proc died"); 4558 exit(1); 4559 } 4560 } 4561 4562 my $test_timeout= start_timer(testcase_timeout($tinfo)); 4563 4564 do_before_run_mysqltest($tinfo); 4565 4566 mark_time_used('admin'); 4567 4568 if ( $opt_check_testcases and check_testcase($tinfo, "before") ){ 4569 # Failed to record state of server or server crashed 4570 report_failure_and_restart($tinfo); 4571 4572 return 1; 4573 } 4574 4575 my $test= start_mysqltest($tinfo); 4576 # Set only when we have to keep waiting after expectedly died server 4577 my $keep_waiting_proc = 0; 4578 my $print_timeout= start_timer($print_freq * 60); 4579 4580 while (1) 4581 { 4582 my $proc; 4583 if ($keep_waiting_proc) 4584 { 4585 # Any other process exited? 4586 $proc = My::SafeProcess->check_any(); 4587 if ($proc) 4588 { 4589 mtr_verbose ("Found exited process $proc"); 4590 } 4591 else 4592 { 4593 $proc = $keep_waiting_proc; 4594 # Also check if timer has expired, if so cancel waiting 4595 if ( has_expired($test_timeout) ) 4596 { 4597 $keep_waiting_proc = 0; 4598 } 4599 } 4600 } 4601 if (! $keep_waiting_proc) 4602 { 4603 if($test_timeout > $print_timeout) 4604 { 4605 $proc= My::SafeProcess->wait_any_timeout($print_timeout); 4606 if ( $proc->{timeout} ) 4607 { 4608 #print out that the test is still on 4609 mtr_print("Test still running: $tinfo->{name}"); 4610 #reset the timer 4611 $print_timeout= start_timer($print_freq * 60); 4612 next; 4613 } 4614 } 4615 else 4616 { 4617 $proc= My::SafeProcess->wait_any_timeout($test_timeout); 4618 } 4619 } 4620 4621 # Will be restored if we need to keep waiting 4622 $keep_waiting_proc = 0; 4623 4624 unless ( defined $proc ) 4625 { 4626 mtr_error("wait_any failed"); 4627 } 4628 mtr_verbose("Got $proc"); 4629 4630 mark_time_used('test'); 4631 # ---------------------------------------------------- 4632 # Was it the test program that exited 4633 # ---------------------------------------------------- 4634 if ($proc eq $test) 4635 { 4636 my $res= $test->exit_status(); 4637 4638 if ($res == 0 and $opt_warnings and check_warnings($tinfo) ) 4639 { 4640 # Test case suceeded, but it has produced unexpected 4641 # warnings, continue in $res == 1 4642 $res= 1; 4643 resfile_output($tinfo->{'warnings'}) if $opt_resfile; 4644 } 4645 4646 if ( $res == 0 ) 4647 { 4648 my $check_res; 4649 if ( restart_forced_by_test('force_restart') ) 4650 { 4651 stop_all_servers($opt_shutdown_timeout); 4652 } 4653 elsif ( $opt_check_testcases and 4654 $check_res= check_testcase($tinfo, "after")) 4655 { 4656 if ($check_res == 1) { 4657 # Test case had sideeffects, not fatal error, just continue 4658 stop_all_servers($opt_shutdown_timeout); 4659 mtr_report("Resuming tests...\n"); 4660 resfile_output($tinfo->{'check'}) if $opt_resfile; 4661 } 4662 else { 4663 # Test case check failed fatally, probably a server crashed 4664 report_failure_and_restart($tinfo); 4665 return 1; 4666 } 4667 } 4668 mtr_report_test_passed($tinfo); 4669 } 4670 elsif ( $res == 62 ) 4671 { 4672 # Testcase itself tell us to skip this one 4673 $tinfo->{skip_reason} = MTR_SKIP_BY_TEST; 4674 # Try to get reason from test log file 4675 find_testcase_skipped_reason($tinfo); 4676 mtr_report_test_skipped($tinfo); 4677 # Restart if skipped due to missing perl, it may have had side effects 4678 if ( restart_forced_by_test('force_restart_if_skipped') || 4679 $tinfo->{'comment'} =~ /^perl not found/ ) 4680 { 4681 stop_all_servers($opt_shutdown_timeout); 4682 } 4683 } 4684 elsif ( $res == 65 ) 4685 { 4686 # Testprogram killed by signal 4687 $tinfo->{comment}= 4688 "testprogram crashed(returned code $res)"; 4689 report_failure_and_restart($tinfo); 4690 } 4691 elsif ( $res == 1 ) 4692 { 4693 # Check if the test tool requests that 4694 # an analyze script should be run 4695 my $analyze= find_analyze_request(); 4696 if ($analyze){ 4697 run_on_all($tinfo, "analyze-$analyze"); 4698 } 4699 4700 # Wait a bit and see if a server died, if so report that instead 4701 mtr_milli_sleep(100); 4702 my $srvproc= My::SafeProcess::check_any(); 4703 if ($srvproc && grep($srvproc eq $_, started(all_servers()))) { 4704 $proc= $srvproc; 4705 goto SRVDIED; 4706 } 4707 4708 error_logs_to_comment($tinfo); 4709 4710 # Test case failure reported by mysqltest 4711 report_failure_and_restart($tinfo); 4712 } 4713 else 4714 { 4715 # mysqltest failed, probably crashed 4716 $tinfo->{comment}= 4717 "mysqltest failed with unexpected return code $res\n"; 4718 report_failure_and_restart($tinfo); 4719 } 4720 4721 # Save info from this testcase run to mysqltest.log 4722 if( -f $path_current_testlog) 4723 { 4724 if ($opt_resfile && $res && $res != 62) { 4725 resfile_output_file($path_current_testlog); 4726 } 4727 mtr_appendfile_to_file($path_current_testlog, $path_testlog); 4728 unlink($path_current_testlog); 4729 } 4730 4731 return ($res == 62) ? 0 : $res; 4732 4733 } 4734 4735 # ---------------------------------------------------- 4736 # Check if it was an expected crash 4737 # ---------------------------------------------------- 4738 my $check_crash = check_expected_crash_and_restart($proc); 4739 if ($check_crash) 4740 { 4741 # Keep waiting if it returned 2, if 1 don't wait or stop waiting. 4742 $keep_waiting_proc = 0 if $check_crash == 1; 4743 $keep_waiting_proc = $proc if $check_crash == 2; 4744 next; 4745 } 4746 4747 SRVDIED: 4748 # ---------------------------------------------------- 4749 # Stop the test case timer 4750 # ---------------------------------------------------- 4751 $test_timeout= 0; 4752 4753 # ---------------------------------------------------- 4754 # Check if it was a server that died 4755 # ---------------------------------------------------- 4756 if ( grep($proc eq $_, started(all_servers())) ) 4757 { 4758 # Server failed, probably crashed 4759 $tinfo->{comment}= 4760 "Server $proc failed during test run" . 4761 get_log_from_proc($proc, $tinfo->{name}); 4762 4763 # ---------------------------------------------------- 4764 # It's not mysqltest that has exited, kill it 4765 # ---------------------------------------------------- 4766 $test->kill(); 4767 4768 report_failure_and_restart($tinfo); 4769 return 1; 4770 } 4771 4772 # Try to dump core for mysqltest and all servers 4773 foreach my $proc ($test, started(all_servers())) 4774 { 4775 mtr_print("Trying to dump core for $proc"); 4776 if ($proc->dump_core()) 4777 { 4778 $proc->wait_one(20); 4779 } 4780 } 4781 4782 # ---------------------------------------------------- 4783 # It's not mysqltest that has exited, kill it 4784 # ---------------------------------------------------- 4785 $test->kill(); 4786 4787 # ---------------------------------------------------- 4788 # Check if testcase timer expired 4789 # ---------------------------------------------------- 4790 if ( $proc->{timeout} ) 4791 { 4792 my $log_file_name= $opt_vardir."/log/".$tinfo->{shortname}.".log"; 4793 $tinfo->{comment}= 4794 "Test case timeout after ".testcase_timeout($tinfo). 4795 " seconds\n\n"; 4796 # Add 20 last executed commands from test case log file 4797 if (-e $log_file_name) 4798 { 4799 $tinfo->{comment}.= 4800 "== $log_file_name == \n". 4801 mtr_lastlinesfromfile($log_file_name, 500)."\n"; 4802 } 4803 error_logs_to_comment($tinfo); 4804 $tinfo->{'timeout'}= testcase_timeout($tinfo); # Mark as timeout 4805 run_on_all($tinfo, 'analyze-timeout'); 4806 4807 report_failure_and_restart($tinfo); 4808 return 1; 4809 } 4810 4811 mtr_error("Unhandled process $proc exited"); 4812 } 4813 mtr_error("Should never come here"); 4814} 4815 4816 4817# Extract server log from after the last occurrence of named test 4818# Return as an array of lines 4819# 4820 4821sub extract_server_log ($$) { 4822 my ($error_log, $tname) = @_; 4823 4824 # Open the servers .err log file and read all lines 4825 # belonging to current tets into @lines 4826 my $Ferr = IO::File->new($error_log) 4827 or mtr_error("Could not open file '$error_log' for reading: $!"); 4828 4829 my @lines; 4830 my $found_test= 0; # Set once we've found the log of this test 4831 while ( my $line = <$Ferr> ) 4832 { 4833 if ($found_test) 4834 { 4835 # If test wasn't last after all, discard what we found, test again. 4836 if ( $line =~ /^CURRENT_TEST:/) 4837 { 4838 @lines= (); 4839 $found_test= $line =~ /^CURRENT_TEST: $tname$/; 4840 } 4841 else 4842 { 4843 push(@lines, $line); 4844 if (scalar(@lines) > 1000000) { 4845 $Ferr = undef; 4846 mtr_warning("Too much log from test, bailing out from extracting"); 4847 return (); 4848 } 4849 } 4850 } 4851 else 4852 { 4853 # Search for beginning of test, until found 4854 $found_test= 1 if ($line =~ /^CURRENT_TEST: $tname$/); 4855 } 4856 } 4857 $Ferr = undef; # Close error log file 4858 4859 return @lines; 4860} 4861 4862# Get log from server identified from its $proc object, from named test 4863# Return as a single string 4864# 4865 4866sub get_log_from_proc ($$) { 4867 my ($proc, $name)= @_; 4868 my $srv_log= ""; 4869 4870 foreach my $mysqld (mysqlds()) { 4871 if ($mysqld->{proc} eq $proc) { 4872 my @srv_lines= extract_server_log($mysqld->value('#log-error'), $name); 4873 $srv_log= "\nServer log from this test:\n" . 4874 "----------SERVER LOG START-----------\n". join ("", @srv_lines) . 4875 "----------SERVER LOG END-------------\n"; 4876 last; 4877 } 4878 } 4879 return $srv_log; 4880} 4881 4882# Perform a rough examination of the servers 4883# error log and write all lines that look 4884# suspicious into $error_log.warnings 4885# 4886sub extract_warning_lines ($$) { 4887 my ($error_log, $tname) = @_; 4888 4889 my @lines= extract_server_log($error_log, $tname); 4890 4891# Write all suspicious lines to $error_log.warnings file 4892 my $warning_log = "$error_log.warnings"; 4893 my $Fwarn = IO::File->new($warning_log, "w") 4894 or die("Could not open file '$warning_log' for writing: $!"); 4895 print $Fwarn "Suspicious lines from $error_log\n"; 4896 4897 my @patterns = 4898 ( 4899 qr/^Warning:|mysqld: Warning|\[Warning\]/, 4900 qr/^Error:|\[ERROR\]/, 4901 qr/^==\d+==\s+\S/, # valgrind errors 4902 qr/InnoDB: Warning|InnoDB: Error/, 4903 qr/^safe_mutex:|allocated at line/, 4904 qr/missing DBUG_RETURN/, 4905 qr/Attempting backtrace/, 4906 qr/Assertion .* failed/, 4907 ); 4908 my $skip_valgrind= 0; 4909 4910 my $last_pat= ""; 4911 my $num_rep= 0; 4912 4913 foreach my $line ( @lines ) 4914 { 4915 if ($opt_valgrind_mysqld) { 4916 # Skip valgrind summary from tests where server has been restarted 4917 # Should this contain memory leaks, the final report will find it 4918 # Use a generic pattern for summaries 4919 $skip_valgrind= 1 if $line =~ /^==\d+== [A-Z ]+ SUMMARY:/; 4920 $skip_valgrind= 0 unless $line =~ /^==\d+==/; 4921 next if $skip_valgrind; 4922 } 4923 foreach my $pat ( @patterns ) 4924 { 4925 if ( $line =~ /$pat/ ) 4926 { 4927 # Remove initial timestamp and look for consecutive identical lines 4928 my $line_pat= $line; 4929 $line_pat =~ s/^[0-9:\-\+\.TZ ]*//; 4930 if ($line_pat eq $last_pat) { 4931 $num_rep++; 4932 } else { 4933 # Previous line had been repeated, report that first 4934 if ($num_rep) { 4935 print $Fwarn ".... repeated $num_rep times: $last_pat"; 4936 $num_rep= 0; 4937 } 4938 $last_pat= $line_pat; 4939 print $Fwarn $line; 4940 } 4941 last; 4942 } 4943 } 4944 } 4945 # Catch the case of last warning being repeated 4946 if ($num_rep) { 4947 print $Fwarn ".... repeated $num_rep times: $last_pat"; 4948 } 4949 4950 $Fwarn = undef; # Close file 4951 4952} 4953 4954 4955# Run include/check-warnings.test 4956# 4957# RETURN VALUE 4958# 0 OK 4959# 1 Check failed 4960# 4961sub start_check_warnings ($$) { 4962 my $tinfo= shift; 4963 my $mysqld= shift; 4964 4965 my $name= "warnings-".$mysqld->name(); 4966 4967 my $log_error= $mysqld->value('#log-error'); 4968 # To be communicated to the test 4969 $ENV{MTR_LOG_ERROR}= $log_error; 4970 extract_warning_lines($log_error, $tinfo->{name}); 4971 4972 my $args; 4973 mtr_init_args(\$args); 4974 4975 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 4976 mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld')); 4977 mtr_add_arg($args, "--test-file=%s", "include/check-warnings.test"); 4978 4979 if ( $opt_embedded_server ) 4980 { 4981 4982 # Get the args needed for the embedded server 4983 # and append them to args prefixed 4984 # with --sever-arg= 4985 4986 my $mysqld= $config->group('embedded') 4987 or mtr_error("Could not get [embedded] section"); 4988 4989 my $mysqld_args; 4990 mtr_init_args(\$mysqld_args); 4991 my $extra_opts= get_extra_opts($mysqld, $tinfo); 4992 mysqld_arguments($mysqld_args, $mysqld, $extra_opts); 4993 mtr_add_arg($args, "--server-arg=%s", $_) for @$mysqld_args; 4994 } 4995 4996 my $errfile= "$opt_vardir/tmp/$name.err"; 4997 my $proc= My::SafeProcess->new 4998 ( 4999 name => $name, 5000 path => $exe_mysqltest, 5001 error => $errfile, 5002 output => $errfile, 5003 args => \$args, 5004 user_data => $errfile, 5005 verbose => $opt_verbose, 5006 ); 5007 mtr_verbose("Started $proc"); 5008 return $proc; 5009} 5010 5011 5012# 5013# Loop through our list of processes and check the error log 5014# for unexepcted errors and warnings 5015# 5016sub check_warnings ($) { 5017 my ($tinfo)= @_; 5018 my $res= 0; 5019 5020 my $tname= $tinfo->{name}; 5021 5022 # Clear previous warnings 5023 delete($tinfo->{warnings}); 5024 5025 # Start the mysqltest processes in parallel to save time 5026 # also makes it possible to wait for any process to exit during the check 5027 my %started; 5028 foreach my $mysqld ( mysqlds() ) 5029 { 5030 if ( defined $mysqld->{'proc'} ) 5031 { 5032 my $proc= start_check_warnings($tinfo, $mysqld); 5033 $started{$proc->pid()}= $proc; 5034 } 5035 } 5036 5037 # Return immediately if no check proceess was started 5038 return 0 unless ( keys %started ); 5039 5040 my $timeout= start_timer(check_timeout($tinfo)); 5041 5042 while (1){ 5043 my $result= 0; 5044 my $proc= My::SafeProcess->wait_any_timeout($timeout); 5045 mtr_report("Got $proc"); 5046 5047 if ( delete $started{$proc->pid()} ) { 5048 # One check warning process returned 5049 my $res= $proc->exit_status(); 5050 my $err_file= $proc->user_data(); 5051 5052 if ( $res == 0 or $res == 62 ){ 5053 5054 if ( $res == 0 ) { 5055 # Check completed with problem 5056 my $report= mtr_grab_file($err_file); 5057 # In rare cases on Windows, exit code 62 is lost, so check output 5058 if (IS_WINDOWS and 5059 $report =~ /^The test .* is not supported by this installation/) { 5060 # Extra sanity check 5061 if ($report =~ /^reason: OK$/m) { 5062 $res= 62; 5063 mtr_print("Seems to have lost exit code 62, assume no warn\n"); 5064 goto LOST62; 5065 } 5066 } 5067 # Log to var/log/warnings file 5068 mtr_tofile("$opt_vardir/log/warnings", 5069 $tname."\n".$report); 5070 5071 $tinfo->{'warnings'}.= $report; 5072 $result= 1; 5073 } 5074 LOST62: 5075 if ( $res == 62 ) { 5076 # Test case was ok and called "skip" 5077 # Remove the .err file the check generated 5078 unlink($err_file); 5079 } 5080 5081 if ( keys(%started) == 0){ 5082 # All checks completed 5083 mark_time_used('ch-warn'); 5084 return $result; 5085 } 5086 # Wait for next process to exit 5087 next if not $result; 5088 } 5089 else 5090 { 5091 my $report= mtr_grab_file($err_file); 5092 $tinfo->{comment}.= 5093 "Could not execute 'check-warnings' for ". 5094 "testcase '$tname' (res: $res):\n"; 5095 $tinfo->{comment}.= $report; 5096 5097 $result= 2; 5098 } 5099 } 5100 elsif ( $proc->{timeout} ) { 5101 $tinfo->{comment}.= "Timeout for 'check warnings' expired after " 5102 .check_timeout($tinfo)." seconds"; 5103 $result= 4; 5104 } 5105 else { 5106 # Unknown process returned, most likley a crash, abort everything 5107 $tinfo->{comment}= 5108 "The server $proc crashed while running 'check warnings'". 5109 get_log_from_proc($proc, $tinfo->{name}); 5110 $result= 3; 5111 } 5112 5113 # Kill any check processes still running 5114 map($_->kill(), values(%started)); 5115 5116 mark_time_used('ch-warn'); 5117 return $result; 5118 } 5119 5120 mtr_error("INTERNAL_ERROR: check_warnings"); 5121} 5122 5123 5124# 5125# Loop through our list of processes and look for and entry 5126# with the provided pid, if found check for the file indicating 5127# expected crash and restart it. 5128# 5129sub check_expected_crash_and_restart { 5130 my ($proc)= @_; 5131 5132 foreach my $mysqld ( mysqlds() ) 5133 { 5134 next unless ( $mysqld->{proc} and $mysqld->{proc} eq $proc ); 5135 5136 # Check if crash expected by looking at the .expect file 5137 # in var/tmp 5138 my $expect_file= "$opt_vardir/tmp/".$mysqld->name().".expect"; 5139 if ( -f $expect_file ) 5140 { 5141 mtr_verbose("Crash was expected, file '$expect_file' exists"); 5142 5143 for (my $waits = 0; $waits < 50; mtr_milli_sleep(100), $waits++) 5144 { 5145 # Race condition seen on Windows: try again until file not empty 5146 next if -z $expect_file; 5147 # If last line in expect file starts with "wait" 5148 # sleep a little and try again, thus allowing the 5149 # test script to control when the server should start 5150 # up again. Keep trying for up to 5s at a time. 5151 my $last_line= mtr_lastlinesfromfile($expect_file, 1); 5152 if ($last_line =~ /^wait/ ) 5153 { 5154 mtr_verbose("Test says wait before restart") if $waits == 0; 5155 next; 5156 } 5157 5158 # Ignore any partial or unknown command 5159 next unless $last_line =~ /^restart/; 5160 # If last line begins "restart:", the rest of the line is read as 5161 # extra command line options to add to the restarted mysqld. 5162 # Anything other than 'wait' or 'restart:' (with a colon) will 5163 # result in a restart with original mysqld options. 5164 if ($last_line =~ /restart:(.+)/) { 5165 my @rest_opt= split(' ', $1); 5166 $mysqld->{'restart_opts'}= \@rest_opt; 5167 } else { 5168 delete $mysqld->{'restart_opts'}; 5169 } 5170 unlink($expect_file); 5171 5172 # Start server with same settings as last time 5173 mysqld_start($mysqld, $mysqld->{'started_opts'}); 5174 5175 return 1; 5176 } 5177 # Loop ran through: we should keep waiting after a re-check 5178 return 2; 5179 } 5180 } 5181 5182 # Not an expected crash 5183 return 0; 5184} 5185 5186 5187# Remove all files and subdirectories of a directory 5188sub clean_dir { 5189 my ($dir)= @_; 5190 mtr_verbose("clean_dir: $dir"); 5191 finddepth( 5192 { no_chdir => 1, 5193 wanted => sub { 5194 if (-d $_){ 5195 # A dir 5196 if ($_ eq $dir){ 5197 # The dir to clean 5198 return; 5199 } else { 5200 mtr_verbose("rmdir: '$_'"); 5201 rmdir($_) or mtr_warning("rmdir($_) failed: $!"); 5202 } 5203 } else { 5204 # Hopefully a file 5205 mtr_verbose("unlink: '$_'"); 5206 unlink($_) or mtr_warning("unlink($_) failed: $!"); 5207 } 5208 } 5209 }, 5210 $dir); 5211} 5212 5213 5214sub clean_datadir { 5215 5216 mtr_verbose("Cleaning datadirs..."); 5217 5218 if (started(all_servers()) != 0){ 5219 mtr_error("Trying to clean datadir before all servers stopped"); 5220 } 5221 5222 foreach my $cluster ( clusters() ) 5223 { 5224 my $cluster_dir= "$opt_vardir/".$cluster->{name}; 5225 mtr_verbose(" - removing '$cluster_dir'"); 5226 rmtree($cluster_dir); 5227 5228 } 5229 5230 foreach my $mysqld ( mysqlds() ) 5231 { 5232 my $mysqld_dir= dirname($mysqld->value('datadir')); 5233 if (-d $mysqld_dir ) { 5234 mtr_verbose(" - removing '$mysqld_dir'"); 5235 rmtree($mysqld_dir); 5236 } 5237 } 5238 5239 # Remove all files in tmp and var/tmp 5240 clean_dir("$opt_vardir/tmp"); 5241 if ($opt_tmpdir ne "$opt_vardir/tmp"){ 5242 clean_dir($opt_tmpdir); 5243 } 5244} 5245 5246 5247# 5248# Save datadir before it's removed 5249# 5250sub save_datadir_after_failure($$) { 5251 my ($dir, $savedir)= @_; 5252 5253 mtr_report(" - saving '$dir'"); 5254 my $dir_name= basename($dir); 5255 rename("$dir", "$savedir/$dir_name"); 5256} 5257 5258 5259sub remove_ndbfs_from_ndbd_datadir { 5260 my ($ndbd_datadir)= @_; 5261 # Remove the ndb_*_fs directory from ndbd.X/ dir 5262 foreach my $ndbfs_dir ( glob("$ndbd_datadir/ndb_*_fs") ) 5263 { 5264 next unless -d $ndbfs_dir; # Skip if not a directory 5265 rmtree($ndbfs_dir); 5266 } 5267} 5268 5269 5270sub after_failure ($) { 5271 my ($tinfo)= @_; 5272 5273 mtr_report("Saving datadirs..."); 5274 5275 my $save_dir= "$opt_vardir/log/"; 5276 $save_dir.= $tinfo->{name}; 5277 # Add combination name if any 5278 $save_dir.= "-$tinfo->{combination}" 5279 if defined $tinfo->{combination}; 5280 5281 # Save savedir path for server 5282 $tinfo->{savedir}= $save_dir; 5283 5284 mkpath($save_dir) if ! -d $save_dir; 5285 5286 # Save the used my.cnf file 5287 copy($path_config_file, $save_dir); 5288 5289 # Copy the tmp dir 5290 copytree("$opt_vardir/tmp/", "$save_dir/tmp/"); 5291 5292 if ( clusters() ) { 5293 foreach my $cluster ( clusters() ) { 5294 my $cluster_dir= "$opt_vardir/".$cluster->{name}; 5295 5296 # Remove the fileystem of each ndbd 5297 foreach my $ndbd ( in_cluster($cluster, ndbds()) ) 5298 { 5299 my $ndbd_datadir= $ndbd->value("DataDir"); 5300 remove_ndbfs_from_ndbd_datadir($ndbd_datadir); 5301 } 5302 5303 save_datadir_after_failure($cluster_dir, $save_dir); 5304 } 5305 } 5306 else { 5307 foreach my $mysqld ( mysqlds() ) { 5308 my $data_dir= $mysqld->value('datadir'); 5309 save_datadir_after_failure(dirname($data_dir), $save_dir); 5310 } 5311 } 5312} 5313 5314 5315sub report_failure_and_restart ($) { 5316 my $tinfo= shift; 5317 5318 if ($opt_valgrind_mysqld && ($tinfo->{'warnings'} || $tinfo->{'timeout'})) { 5319 # In these cases we may want valgrind report from normal termination 5320 $tinfo->{'dont_kill_server'}= 1; 5321 } 5322 5323 # Shutdown properly if not to be killed (for valgrind) 5324 stop_all_servers($tinfo->{'dont_kill_server'} ? $opt_shutdown_timeout : 0); 5325 5326 $tinfo->{'result'}= 'MTR_RES_FAILED'; 5327 5328 my $test_failures= $tinfo->{'failures'} || 0; 5329 $tinfo->{'failures'}= $test_failures + 1; 5330 5331 5332 if ( $tinfo->{comment} ) 5333 { 5334 # The test failure has been detected by mysql-test-run.pl 5335 # when starting the servers or due to other error, the reason for 5336 # failing the test is saved in "comment" 5337 ; 5338 } 5339 5340 if ( !defined $tinfo->{logfile} ) 5341 { 5342 my $logfile= $path_current_testlog; 5343 if ( defined $logfile ) 5344 { 5345 if ( -f $logfile ) 5346 { 5347 # Test failure was detected by test tool and its report 5348 # about what failed has been saved to file. Save the report 5349 # in tinfo 5350 $tinfo->{logfile}= mtr_fromfile($logfile); 5351 # If no newlines in the test log: 5352 # (it will contain the CURRENT_TEST written by mtr, so is not empty) 5353 if ($tinfo->{logfile} !~ /\n/) 5354 { 5355 # Show how far it got before suddenly failing 5356 $tinfo->{comment}.= "mysqltest failed but provided no output\n"; 5357 my $log_file_name= $opt_vardir."/log/".$tinfo->{shortname}.".log"; 5358 if (-e $log_file_name) { 5359 $tinfo->{comment}.= 5360 "The result from queries just before the failure was:". 5361 "\n< snip >\n". 5362 mtr_lastlinesfromfile($log_file_name, 500)."\n"; 5363 } 5364 } 5365 } 5366 else 5367 { 5368 # The test tool report didn't exist, display an 5369 # error message 5370 $tinfo->{logfile}= "Could not open test tool report '$logfile'"; 5371 } 5372 } 5373 } 5374 5375 after_failure($tinfo); 5376 5377 mtr_report_test($tinfo); 5378 5379} 5380 5381 5382sub run_sh_script { 5383 my ($script)= @_; 5384 5385 return 0 unless defined $script; 5386 5387 mtr_verbose("Running '$script'"); 5388 my $ret= system("/bin/sh $script") >> 8; 5389 return $ret; 5390} 5391 5392 5393sub mysqld_stop { 5394 my $mysqld= shift or die "usage: mysqld_stop(<mysqld>)"; 5395 5396 my $args; 5397 mtr_init_args(\$args); 5398 5399 mtr_add_arg($args, "--no-defaults"); 5400 mtr_add_arg($args, "--character-sets-dir=%s", $mysqld->value('character-sets-dir')); 5401 mtr_add_arg($args, "--user=%s", $opt_user); 5402 mtr_add_arg($args, "--password="); 5403 mtr_add_arg($args, "--port=%d", $mysqld->value('port')); 5404 mtr_add_arg($args, "--host=%s", $mysqld->value('#host')); 5405 mtr_add_arg($args, "--connect_timeout=20"); 5406 mtr_add_arg($args, "--protocol=tcp"); 5407 5408 mtr_add_arg($args, "shutdown"); 5409 5410 My::SafeProcess->run 5411 ( 5412 name => "mysqladmin shutdown ".$mysqld->name(), 5413 path => $exe_mysqladmin, 5414 args => \$args, 5415 error => "/dev/null", 5416 5417 ); 5418} 5419 5420 5421sub mysqld_arguments ($$$) { 5422 my $args= shift; 5423 my $mysqld= shift; 5424 my $extra_opts= shift; 5425 5426 my @defaults = grep(/^--defaults-file=/, @$extra_opts); 5427 if (@defaults > 0) { 5428 mtr_add_arg($args, pop(@defaults)) 5429 } 5430 else { 5431 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 5432 } 5433 5434 # When mysqld is run by a root user(euid is 0), it will fail 5435 # to start unless we specify what user to run as, see BUG#30630 5436 my $euid= $>; 5437 if (!IS_WINDOWS and $euid == 0 and 5438 (grep(/^--user/, @$extra_opts)) == 0) { 5439 mtr_add_arg($args, "--user=root"); 5440 } 5441 5442 if ( $opt_valgrind_mysqld ) 5443 { 5444 if ( $mysql_version_id < 50100 ) 5445 { 5446 mtr_add_arg($args, "--skip-bdb"); 5447 } 5448 } 5449 5450 # On some old linux kernels, aio on tmpfs is not supported 5451 # Remove this if/when Bug #58421 fixes this in the server 5452 if ($^O eq "linux" && $opt_mem) 5453 { 5454 mtr_add_arg($args, "--loose-skip-innodb-use-native-aio"); 5455 } 5456 5457 if ( $mysql_version_id >= 50106 && !$opt_user_args) 5458 { 5459 # Turn on logging to file 5460 mtr_add_arg($args, "--log-output=file"); 5461 } 5462 5463 # Check if "extra_opt" contains skip-log-bin 5464 my $skip_binlog= grep(/^(--|--loose-)skip-log-bin/, @$extra_opts); 5465 5466 # Indicate to mysqld it will be debugged in debugger 5467 if ( $glob_debugger ) 5468 { 5469 mtr_add_arg($args, "--gdb"); 5470 } 5471 5472 # Enable the debug sync facility, set default wait timeout. 5473 # Facility stays disabled if timeout value is zero. 5474 mtr_add_arg($args, "--loose-debug-sync-timeout=%s", 5475 $opt_debug_sync_timeout) unless $opt_user_args; 5476 5477 # Options specified in .opt files should be added last so they can 5478 # override defaults above. 5479 5480 my $found_skip_core= 0; 5481 my $found_no_console= 0; 5482 my $found_log_error= 0; 5483 5484 # On windows, do not add console if log-error found in .cnf file 5485 open (CONFIG_FILE, " < $path_config_file") or 5486 die("Could not open output file $path_config_file"); 5487 5488 while (<CONFIG_FILE>) 5489 { 5490 if (m/^log[-_]error/) 5491 { 5492 $found_log_error= 1; 5493 } 5494 } 5495 close (CONFIG_FILE); 5496 5497 foreach my $arg ( @$extra_opts ) 5498 { 5499 # Skip --defaults-file option since it's handled above. 5500 next if $arg =~ /^--defaults-file/; 5501 5502 if ($arg =~ /^--log[-_]error/) 5503 { 5504 $found_log_error= 1; 5505 } 5506 5507 # Allow --skip-core-file to be set in <testname>-[master|slave].opt file 5508 if ($arg eq "--skip-core-file") 5509 { 5510 $found_skip_core= 1; 5511 } 5512 elsif ($arg eq "--no-console") 5513 { 5514 $found_no_console= 1; 5515 } 5516 elsif ($skip_binlog and mtr_match_prefix($arg, "--binlog-format")) 5517 { 5518 ; # Dont add --binlog-format when running without binlog 5519 } 5520 elsif ($arg eq "--loose-skip-log-bin" and 5521 $mysqld->option("log-slave-updates")) 5522 { 5523 ; # Dont add --skip-log-bin when mysqld have --log-slave-updates in config 5524 } 5525 elsif ($arg eq "") 5526 { 5527 # We can get an empty argument when we set environment variables to "" 5528 # (e.g plugin not found). Just skip it. 5529 } 5530 else 5531 { 5532 mtr_add_arg($args, "%s", $arg); 5533 } 5534 } 5535 $opt_skip_core = $found_skip_core; 5536 if (IS_WINDOWS && !$found_no_console && !$found_log_error) 5537 { 5538 # Trick the server to send output to stderr, with --console 5539 mtr_add_arg($args, "--console"); 5540 } 5541 if ( !$found_skip_core && !$opt_user_args ) 5542 { 5543 mtr_add_arg($args, "%s", "--core-file"); 5544 } 5545 5546 return $args; 5547} 5548 5549 5550 5551sub mysqld_start ($$) { 5552 my $mysqld= shift; 5553 my $extra_opts= shift; 5554 5555 mtr_verbose(My::Options::toStr("mysqld_start", @$extra_opts)); 5556 5557 my $exe= find_mysqld($mysqld->value('basedir')); 5558 my $wait_for_pid_file= 1; 5559 5560 mtr_error("Internal error: mysqld should never be started for embedded") 5561 if $opt_embedded_server; 5562 5563 my $args; 5564 mtr_init_args(\$args); 5565# implementation for strace-server 5566 if ( $opt_strace_server ) 5567 { 5568 strace_server_arguments($args, \$exe, $mysqld->name()); 5569 } 5570 5571 5572 if ( $opt_valgrind_mysqld ) 5573 { 5574 valgrind_arguments($args, \$exe, $mysqld->name()); 5575 } 5576 5577 mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld')); 5578 5579 # Add any additional options from an in-test restart 5580 my @all_opts= @$extra_opts; 5581 if (exists $mysqld->{'restart_opts'}) { 5582 push (@all_opts, @{$mysqld->{'restart_opts'}}); 5583 mtr_verbose(My::Options::toStr("mysqld_start restart", 5584 @{$mysqld->{'restart_opts'}})); 5585 } 5586 mysqld_arguments($args,$mysqld,\@all_opts); 5587 5588 if ( $opt_debug ) 5589 { 5590 mtr_add_arg($args, "--debug=$debug_d:t:i:A,%s/log/%s.trace", 5591 $path_vardir_trace, $mysqld->name()); 5592 } 5593 5594 if ( $opt_gdb || $opt_manual_gdb ) 5595 { 5596 gdb_arguments(\$args, \$exe, $mysqld->name()); 5597 } 5598 elsif ( $opt_lldb || $opt_manual_lldb ) 5599 { 5600 lldb_arguments(\$args, \$exe, $mysqld->name()); 5601 } 5602 elsif ( $opt_ddd || $opt_manual_ddd ) 5603 { 5604 ddd_arguments(\$args, \$exe, $mysqld->name()); 5605 } 5606 if ( $opt_dbx || $opt_manual_dbx ) { 5607 dbx_arguments(\$args, \$exe, $mysqld->name()); 5608 } 5609 elsif ( $opt_debugger ) 5610 { 5611 debugger_arguments(\$args, \$exe, $mysqld->name()); 5612 } 5613 elsif ( $opt_manual_debug ) 5614 { 5615 print "\nStart " .$mysqld->name()." in your debugger\n" . 5616 "dir: $glob_mysql_test_dir\n" . 5617 "exe: $exe\n" . 5618 "args: " . join(" ", @$args) . "\n\n" . 5619 "Waiting ....\n"; 5620 5621 # Indicate the exe should not be started 5622 $exe= undef; 5623 } 5624 else 5625 { 5626 # Default to not wait until pid file has been created 5627 $wait_for_pid_file= 0; 5628 } 5629 5630 # Remove the old pidfile if any 5631 unlink($mysqld->value('pid-file')); 5632 5633 my $output= $mysqld->value('#log-error'); 5634 5635 # Remember this log file for valgrind/shutdown error report search 5636 $mysqld_logs{$output}= 1; 5637 5638 # Remember data dir for gmon.out files if using gprof 5639 $gprof_dirs{$mysqld->value('datadir')}= 1 if $opt_gprof; 5640 5641 if ( defined $exe ) 5642 { 5643 $mysqld->{'proc'}= My::SafeProcess->new 5644 ( 5645 name => $mysqld->name(), 5646 path => $exe, 5647 args => \$args, 5648 output => $output, 5649 error => $output, 5650 append => 1, 5651 verbose => $opt_verbose, 5652 nocore => $opt_skip_core, 5653 host => undef, 5654 shutdown => sub { mysqld_stop($mysqld) }, 5655 envs => \@opt_mysqld_envs, 5656 ); 5657 mtr_verbose("Started $mysqld->{proc}"); 5658 } 5659 5660 if ( $wait_for_pid_file && 5661 !sleep_until_file_created($mysqld->value('pid-file'), 5662 $opt_start_timeout, 5663 $mysqld->{'proc'})) 5664 { 5665 my $mname= $mysqld->name(); 5666 mtr_error("Failed to start mysqld $mname with command $exe"); 5667 } 5668 5669 # Remember options used when starting 5670 $mysqld->{'started_opts'}= $extra_opts; 5671 5672 return; 5673} 5674 5675sub shutdown_processes { 5676 my ($timeout, @servers)= @_; 5677 my $append_exit_reports= 0; 5678 my %status = My::SafeProcess::shutdown($timeout, @servers); 5679 5680 if ($status{failed}) { 5681 $shutdown_report_text.= "mysqld abnormal exit\n"; 5682 } 5683 if ($status{killed}) { 5684 $shutdown_report_text.= 5685 "mysqld was killed after it failed to properly shutdown\n"; 5686 } 5687 5688 if ($status{failed} or $status{killed}) { 5689 $shutdown_report = 1; 5690 my $reports= shutdown_exit_reports(); 5691 while (my ($log_file, $report) = each (%$reports)) { 5692 $shutdown_report_text.= $log_file . " after tests: @{$report->{after_tests}}:\n". 5693 "----------SERVER LOG START-----------\n". 5694 $report->{text}. 5695 "----------SERVER LOG END-------------\n"; 5696 } 5697 } 5698} 5699 5700sub stop_all_servers () { 5701 my $shutdown_timeout = $_[0] or 0; 5702 5703 mtr_verbose("Stopping all servers..."); 5704 5705 # Kill all started servers 5706 shutdown_processes($shutdown_timeout, 5707 started(all_servers())); 5708 5709 # Remove pidfiles 5710 foreach my $server ( all_servers() ) 5711 { 5712 my $pid_file= $server->if_exist('pid-file'); 5713 unlink($pid_file) if defined $pid_file; 5714 } 5715 5716 # Mark servers as stopped 5717 map($_->{proc} = undef, all_servers()); 5718} 5719 5720 5721# Find out if server should be restarted for this test 5722sub server_need_restart { 5723 my ($tinfo, $server)= @_; 5724 5725 # Mark the tinfo so slaves will restart if server restarts 5726 # This assumes master will be considered first. 5727 my $is_master= $server->option("#!run-master-sh"); 5728 5729 if ( using_extern() ) 5730 { 5731 mtr_verbose_restart($server, "no restart for --extern server"); 5732 return 0; 5733 } 5734 5735 if ( $tinfo->{'force_restart'} ) { 5736 mtr_verbose_restart($server, "forced in .opt file"); 5737 $tinfo->{master_restart}= 1 if $is_master; 5738 return 1; 5739 } 5740 5741 if ( $opt_force_restart ) { 5742 mtr_verbose_restart($server, "forced restart turned on"); 5743 $tinfo->{master_restart}= 1 if $is_master; 5744 return 1; 5745 } 5746 5747 if ( $tinfo->{template_path} ne $current_config_name) 5748 { 5749 mtr_verbose_restart($server, "using different config file"); 5750 $tinfo->{master_restart}= 1 if $is_master; 5751 return 1; 5752 } 5753 5754 if ( $tinfo->{'master_sh'} || $tinfo->{'slave_sh'} ) 5755 { 5756 mtr_verbose_restart($server, "sh script to run"); 5757 $tinfo->{master_restart}= 1 if $is_master; 5758 return 1; 5759 } 5760 5761 if ( ! started($server) ) 5762 { 5763 mtr_verbose_restart($server, "not started"); 5764 $tinfo->{master_restart}= 1 if $is_master; 5765 return 1; 5766 } 5767 5768 my $started_tinfo= $server->{'started_tinfo'}; 5769 if ( defined $started_tinfo ) 5770 { 5771 5772 # Check if timezone of test that server was started 5773 # with differs from timezone of next test 5774 if ( timezone($started_tinfo) ne timezone($tinfo) ) 5775 { 5776 mtr_verbose_restart($server, "different timezone"); 5777 $tinfo->{master_restart}= 1 if $is_master; 5778 return 1; 5779 } 5780 } 5781 5782 my $is_mysqld= grep ($server eq $_, mysqlds()); 5783 if ($is_mysqld) 5784 { 5785 5786 # Check that running process was started with same options 5787 # as the current test requires 5788 my $extra_opts= get_extra_opts($server, $tinfo); 5789 my $started_opts= $server->{'started_opts'}; 5790 5791 # Also, always restart if server had been restarted with additional 5792 # options within test. 5793 if (!My::Options::same($started_opts, $extra_opts) || 5794 exists $server->{'restart_opts'}) 5795 { 5796 my $use_dynamic_option_switch= 0; 5797 if (!$use_dynamic_option_switch) 5798 { 5799 mtr_verbose_restart($server, "running with different options '" . 5800 join(" ", @{$extra_opts}) . "' != '" . 5801 join(" ", @{$started_opts}) . "'" ); 5802 $tinfo->{master_restart}= 1 if $is_master; 5803 return 1; 5804 } 5805 5806 mtr_verbose(My::Options::toStr("started_opts", @$started_opts)); 5807 mtr_verbose(My::Options::toStr("extra_opts", @$extra_opts)); 5808 5809 # Get diff and check if dynamic switch is possible 5810 my @diff_opts= My::Options::diff($started_opts, $extra_opts); 5811 mtr_verbose(My::Options::toStr("diff_opts", @diff_opts)); 5812 5813 my $query= My::Options::toSQL(@diff_opts); 5814 mtr_verbose("Attempting dynamic switch '$query'"); 5815 if (run_query($tinfo, $server, $query)){ 5816 mtr_verbose("Restart: running with different options '" . 5817 join(" ", @{$extra_opts}) . "' != '" . 5818 join(" ", @{$started_opts}) . "'" ); 5819 $tinfo->{master_restart}= 1 if $is_master; 5820 return 1; 5821 } 5822 5823 # Remember the dynamically set options 5824 $server->{'started_opts'}= $extra_opts; 5825 } 5826 } 5827 5828 if ($server->option("#!use-slave-opt") && $tinfo->{master_restart}) { 5829 mtr_verbose_restart($server, "master will be restarted"); 5830 return 1; 5831 } 5832 5833 # Default, no restart 5834 return 0; 5835} 5836 5837 5838sub servers_need_restart($) { 5839 my ($tinfo)= @_; 5840 return grep { server_need_restart($tinfo, $_); } all_servers(); 5841} 5842 5843 5844 5845# 5846# Return list of specific servers 5847# - there is no servers in an empty config 5848# 5849sub _like { return $config ? $config->like($_[0]) : (); } 5850sub mysqlds { return _like('mysqld.'); } 5851sub ndbds { return _like('cluster_config.ndbd.');} 5852sub ndb_mgmds { return _like('cluster_config.ndb_mgmd.'); } 5853sub clusters { return _like('mysql_cluster.'); } 5854sub memcacheds { return _like('memcached.'); } 5855sub all_servers { return ( mysqlds(), ndb_mgmds(), ndbds(), memcacheds() ); } 5856 5857# 5858# Filter a list of servers and return only those that are part 5859# of the specified cluster 5860# 5861sub in_cluster { 5862 my ($cluster)= shift; 5863 # Return only processes for a specific cluster 5864 return grep { $_->suffix() eq $cluster->suffix() } @_; 5865} 5866 5867 5868 5869# 5870# Filter a list of servers and return the SafeProcess 5871# for only those that are started or stopped 5872# 5873sub started { return grep(defined $_, map($_->{proc}, @_)); } 5874sub stopped { return grep(!defined $_, map($_->{proc}, @_)); } 5875 5876 5877sub envsubst { 5878 my $string= shift; 5879# Check for the ? symbol in the var name and remove it. 5880 if ( $string =~ s/^\?// ) 5881 { 5882 if ( ! defined $ENV{$string} ) 5883 { 5884 return ""; 5885 } 5886 } 5887 else 5888 { 5889 if ( ! defined $ENV{$string} ) 5890 { 5891 mtr_error(".opt file references '$string' which is not set"); 5892 } 5893 } 5894 5895 return $ENV{$string}; 5896} 5897 5898 5899sub get_extra_opts { 5900 # No extra options if --user-args 5901 return \@opt_extra_mysqld_opt if $opt_user_args; 5902 5903 my ($mysqld, $tinfo)= @_; 5904 5905 my $opts= 5906 $mysqld->option("#!use-slave-opt") ? 5907 $tinfo->{slave_opt} : $tinfo->{master_opt}; 5908 5909 # Expand environment variables 5910 foreach my $opt ( @$opts ) 5911 { 5912 $opt =~ s/\$\{(\??\w+)\}/envsubst($1)/ge; 5913 $opt =~ s/\$(\??\w+)/envsubst($1)/ge; 5914 } 5915 return $opts; 5916} 5917 5918 5919sub stop_servers($$) { 5920 my ($tinfo, @servers)= @_; 5921 5922 # Remember if we restarted for this test case (count restarts) 5923 $tinfo->{'restarted'} = 1; 5924 5925 if ( join('|', @servers) eq join('|', all_servers()) ) 5926 { 5927 # All servers are going down, use some kind of order to 5928 # avoid too many warnings in the log files 5929 5930 mtr_report("Restarting all servers"); 5931 5932 # mysqld processes 5933 shutdown_processes($opt_shutdown_timeout, 5934 started(mysqlds())); 5935 5936 # cluster processes 5937 shutdown_processes($opt_shutdown_timeout, 5938 started(ndbds(), ndb_mgmds(), memcacheds())); 5939 } 5940 else 5941 { 5942 mtr_report("Restarting ", started(@servers)); 5943 5944 # Stop only some servers 5945 shutdown_processes($opt_shutdown_timeout, 5946 started(@servers)); 5947 } 5948 5949 foreach my $server (@servers) 5950 { 5951 # Mark server as stopped 5952 $server->{proc}= undef; 5953 5954 # Forget history 5955 delete $server->{'started_tinfo'}; 5956 delete $server->{'started_opts'}; 5957 delete $server->{'started_cnf'}; 5958 } 5959} 5960 5961 5962# 5963# start_servers 5964# 5965# Start servers not already started 5966# 5967# RETURN 5968# 0 OK 5969# 1 Start failed 5970# 5971sub start_servers($) { 5972 my ($tinfo)= @_; 5973 5974 # Make sure the safe_process also exits from now on 5975 # Could not be done before, as we don't want this for the bootstrap 5976 if ($opt_start_exit) { 5977 My::SafeProcess->start_exit(); 5978 } 5979 5980 # Start clusters 5981 foreach my $cluster ( clusters() ) 5982 { 5983 ndbcluster_start($cluster); 5984 } 5985 5986 # Start mysqlds 5987 foreach my $mysqld ( mysqlds() ) 5988 { 5989 if ( $mysqld->{proc} ) 5990 { 5991 # Already started 5992 5993 # Write start of testcase to log file 5994 mark_log($mysqld->value('#log-error'), $tinfo); 5995 5996 next; 5997 } 5998 5999 my $datadir= $mysqld->value('datadir'); 6000 if ($opt_start_dirty) 6001 { 6002 # Don't delete anything if starting dirty 6003 ; 6004 } 6005 else 6006 { 6007 6008 my @options= ('log-bin', 'relay-log'); 6009 foreach my $option_name ( @options ) { 6010 next unless $mysqld->option($option_name); 6011 6012 my $file_name= $mysqld->value($option_name); 6013 next unless 6014 defined $file_name and 6015 -e $file_name; 6016 6017 mtr_debug(" -removing '$file_name'"); 6018 unlink($file_name) or die ("unable to remove file '$file_name'"); 6019 } 6020 6021 if (-d $datadir ) { 6022 mtr_verbose(" - removing '$datadir'"); 6023 rmtree($datadir); 6024 } 6025 } 6026 6027 my $mysqld_basedir= $mysqld->value('basedir'); 6028 if ( $basedir eq $mysqld_basedir ) 6029 { 6030 if (!$opt_start_dirty) # If dirty, keep possibly grown system db 6031 { 6032 # Copy datadir from installed system db 6033 my $path= ($opt_parallel == 1) ? "$opt_vardir" : "$opt_vardir/.."; 6034 my $install_db= "$path/install.db"; 6035 copytree($install_db, $datadir) if -d $install_db; 6036 mtr_error("Failed to copy system db to '$datadir'") 6037 unless -d $datadir; 6038 } 6039 } 6040 else 6041 { 6042 mysql_install_db($mysqld); # For versional testing 6043 6044 mtr_error("Failed to install system db to '$datadir'") 6045 unless -d $datadir; 6046 6047 } 6048 6049 # Create the servers tmpdir 6050 my $tmpdir= $mysqld->value('tmpdir'); 6051 mkpath($tmpdir) unless -d $tmpdir; 6052 6053 # Write start of testcase to log file 6054 mark_log($mysqld->value('#log-error'), $tinfo); 6055 6056 # Run <tname>-master.sh 6057 if ($mysqld->option('#!run-master-sh') and 6058 run_sh_script($tinfo->{master_sh}) ) 6059 { 6060 $tinfo->{'comment'}= "Failed to execute '$tinfo->{master_sh}'"; 6061 return 1; 6062 } 6063 6064 # Run <tname>-slave.sh 6065 if ($mysqld->option('#!run-slave-sh') and 6066 run_sh_script($tinfo->{slave_sh})) 6067 { 6068 $tinfo->{'comment'}= "Failed to execute '$tinfo->{slave_sh}'"; 6069 return 1; 6070 } 6071 6072 if (!$opt_embedded_server) 6073 { 6074 my $extra_opts= get_extra_opts($mysqld, $tinfo); 6075 mysqld_start($mysqld,$extra_opts); 6076 6077 # Save this test case information, so next can examine it 6078 $mysqld->{'started_tinfo'}= $tinfo; 6079 6080 # Wait until server's uuid is generated. This avoids that master and 6081 # slave generate the same UUID sporadically. 6082 sleep_until_file_created("$datadir/auto.cnf", $opt_start_timeout, 6083 $mysqld->{'proc'}); 6084 6085 } 6086 6087 } 6088 6089 # Wait for clusters to start 6090 foreach my $cluster ( clusters() ) 6091 { 6092 if (ndbcluster_wait_started($cluster, "")) 6093 { 6094 # failed to start 6095 $tinfo->{'comment'}= "Start of '".$cluster->name()."' cluster failed"; 6096 6097 # 6098 # Dump cluster log files to log file to help analyze the 6099 # cause of the failed start 6100 # 6101 ndbcluster_dump($cluster); 6102 6103 return 1; 6104 } 6105 } 6106 6107 # Wait for mysqlds to start 6108 foreach my $mysqld ( mysqlds() ) 6109 { 6110 next if !started($mysqld); 6111 6112 if (sleep_until_file_created($mysqld->value('pid-file'), 6113 $opt_start_timeout, 6114 $mysqld->{'proc'}) == 0) { 6115 $tinfo->{comment}= 6116 "Failed to start ".$mysqld->name(); 6117 6118 my $logfile= $mysqld->value('#log-error'); 6119 if ( defined $logfile and -f $logfile ) 6120 { 6121 my @srv_lines= extract_server_log($logfile, $tinfo->{name}); 6122 $tinfo->{logfile}= "Server log is:\n" . join ("", @srv_lines); 6123 } 6124 else 6125 { 6126 $tinfo->{logfile}= "Could not open server logfile: '$logfile'"; 6127 } 6128 return 1; 6129 } 6130 } 6131 6132 # Start memcached(s) for each cluster 6133 foreach my $cluster ( clusters() ) 6134 { 6135 next if !in_cluster($cluster, memcacheds()); 6136 6137 # Load the memcache metadata into this cluster 6138 memcached_load_metadata($cluster); 6139 6140 # Start memcached(s) 6141 foreach my $memcached ( in_cluster($cluster, memcacheds())) 6142 { 6143 next if started($memcached); 6144 memcached_start($cluster, $memcached); 6145 } 6146 } 6147 6148 return 0; 6149} 6150 6151 6152# 6153# Run include/check-testcase.test 6154# Before a testcase, run in record mode and save result file to var/tmp 6155# After testcase, run and compare with the recorded file, they should be equal! 6156# 6157# RETURN VALUE 6158# The newly started process 6159# 6160sub start_check_testcase ($$$) { 6161 my $tinfo= shift; 6162 my $mode= shift; 6163 my $mysqld= shift; 6164 6165 my $name= "check-".$mysqld->name(); 6166 # Replace dots in name with underscore to avoid that mysqltest 6167 # misinterpret's what the filename extension is :( 6168 $name=~ s/\./_/g; 6169 6170 my $args; 6171 mtr_init_args(\$args); 6172 6173 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 6174 mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld')); 6175 mtr_add_arg($args, "--result-file=%s", "$opt_vardir/tmp/$name.result"); 6176 mtr_add_arg($args, "--test-file=%s", "include/check-testcase.test"); 6177 mtr_add_arg($args, "--verbose"); 6178 mtr_add_arg($args, "--logdir=%s/tmp", $opt_vardir); 6179 6180 if ( $mode eq "before" ) 6181 { 6182 mtr_add_arg($args, "--record"); 6183 } 6184 my $errfile= "$opt_vardir/tmp/$name.err"; 6185 my $proc= My::SafeProcess->new 6186 ( 6187 name => $name, 6188 path => $exe_mysqltest, 6189 error => $errfile, 6190 output => $errfile, 6191 args => \$args, 6192 user_data => $errfile, 6193 verbose => $opt_verbose, 6194 ); 6195 6196 mtr_report("Started $proc"); 6197 return $proc; 6198} 6199 6200 6201sub run_mysqltest ($) { 6202 my $proc= start_mysqltest(@_); 6203 $proc->wait(); 6204} 6205 6206 6207sub start_mysqltest ($) { 6208 my ($tinfo)= @_; 6209 my $exe= $exe_mysqltest; 6210 my $args; 6211 6212 mark_time_used('admin'); 6213 6214 mtr_init_args(\$args); 6215 6216 if ( $opt_strace_client ) 6217 { 6218 $exe= "strace"; 6219 mtr_add_arg($args, "-o"); 6220 mtr_add_arg($args, "%s/log/mysqltest.strace", $opt_vardir); 6221 mtr_add_arg($args, "-f"); 6222 mtr_add_arg($args, "$exe_mysqltest"); 6223 } 6224 6225 mtr_add_arg($args, "--defaults-file=%s", $path_config_file); 6226 mtr_add_arg($args, "--silent"); 6227 mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); 6228 mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); 6229 mtr_add_arg($args, "--logdir=%s/log", $opt_vardir); 6230 if ($auth_plugin) 6231 { 6232 mtr_add_arg($args, "--plugin_dir=%s", dirname($auth_plugin)); 6233 } 6234 6235 # Log line number and time for each line in .test file 6236 mtr_add_arg($args, "--mark-progress") 6237 if $opt_mark_progress; 6238 6239 mtr_add_arg($args, "--database=test"); 6240 6241 if ( $opt_ps_protocol ) 6242 { 6243 mtr_add_arg($args, "--ps-protocol"); 6244 } 6245 6246 if ( $opt_sp_protocol ) 6247 { 6248 mtr_add_arg($args, "--sp-protocol"); 6249 } 6250 6251 if ( $opt_explain_protocol ) 6252 { 6253 mtr_add_arg($args, "--explain-protocol"); 6254 } 6255 6256 if ( $opt_json_explain_protocol ) 6257 { 6258 mtr_add_arg($args, "--json-explain-protocol"); 6259 } 6260 6261 if ( $opt_view_protocol ) 6262 { 6263 mtr_add_arg($args, "--view-protocol"); 6264 } 6265 6266 if ( $opt_trace_protocol ) 6267 { 6268 mtr_add_arg($args, "--opt-trace-protocol"); 6269 } 6270 6271 if ( $opt_cursor_protocol ) 6272 { 6273 mtr_add_arg($args, "--cursor-protocol"); 6274 } 6275 6276 6277 mtr_add_arg($args, "--timer-file=%s/log/timer", $opt_vardir); 6278 6279 if ( $opt_compress ) 6280 { 6281 mtr_add_arg($args, "--compress"); 6282 } 6283 6284 if ( $opt_sleep ) 6285 { 6286 mtr_add_arg($args, "--sleep=%d", $opt_sleep); 6287 } 6288 6289 if ( $opt_ssl ) 6290 { 6291 # Turn on SSL for _all_ test cases if option --ssl was used 6292 mtr_add_arg($args, "--ssl"); 6293 } 6294 6295 if ( $opt_max_connections ) { 6296 mtr_add_arg($args, "--max-connections=%d", $opt_max_connections); 6297 } 6298 6299 if ( $opt_embedded_server ) 6300 { 6301 6302 # Get the args needed for the embedded server 6303 # and append them to args prefixed 6304 # with --sever-arg= 6305 6306 my $mysqld= $config->group('embedded') 6307 or mtr_error("Could not get [embedded] section"); 6308 6309 my $mysqld_args; 6310 mtr_init_args(\$mysqld_args); 6311 my $extra_opts= get_extra_opts($mysqld, $tinfo); 6312 mysqld_arguments($mysqld_args, $mysqld, $extra_opts); 6313 mtr_add_arg($args, "--server-arg=%s", $_) for @$mysqld_args; 6314 } 6315 6316 # ---------------------------------------------------------------------- 6317 # export MYSQL_TEST variable containing <path>/mysqltest <args> 6318 # ---------------------------------------------------------------------- 6319 $ENV{'MYSQL_TEST'}= mtr_args2str($exe_mysqltest, @$args); 6320 6321 # ---------------------------------------------------------------------- 6322 # Add arguments that should not go into the MYSQL_TEST env var 6323 # ---------------------------------------------------------------------- 6324 if ( $opt_valgrind_mysqltest ) 6325 { 6326 # Prefix the Valgrind options to the argument list. 6327 # We do this here, since we do not want to Valgrind the nested invocations 6328 # of mysqltest; that would mess up the stderr output causing test failure. 6329 my @args_saved = @$args; 6330 mtr_init_args(\$args); 6331 valgrind_arguments($args, \$exe); 6332 mtr_add_arg($args, "%s", $_) for @args_saved; 6333 } 6334 6335 mtr_add_arg($args, "--test-file=%s", $tinfo->{'path'}); 6336 6337 # Number of lines of resut to include in failure report 6338 mtr_add_arg($args, "--tail-lines=500"); 6339 6340 if ( defined $tinfo->{'result_file'} ) { 6341 mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'}); 6342 } 6343 6344 client_debug_arg($args, "mysqltest"); 6345 6346 if ( $opt_record ) 6347 { 6348 mtr_add_arg($args, "--record"); 6349 6350 # When recording to a non existing result file 6351 # the name of that file is in "record_file" 6352 if ( defined $tinfo->{'record_file'} ) { 6353 mtr_add_arg($args, "--result-file=%s", $tinfo->{record_file}); 6354 } 6355 } 6356 6357 if ( $opt_client_gdb ) 6358 { 6359 gdb_arguments(\$args, \$exe, "client"); 6360 } 6361 elsif ( $opt_client_ddd ) 6362 { 6363 ddd_arguments(\$args, \$exe, "client"); 6364 } 6365 if ( $opt_client_dbx ) { 6366 dbx_arguments(\$args, \$exe, "client"); 6367 } 6368 elsif ( $opt_client_debugger ) 6369 { 6370 debugger_arguments(\$args, \$exe, "client"); 6371 } 6372 6373 my $proc= My::SafeProcess->new 6374 ( 6375 name => "mysqltest", 6376 path => $exe, 6377 args => \$args, 6378 append => 1, 6379 error => $path_current_testlog, 6380 verbose => $opt_verbose, 6381 ); 6382 mtr_verbose("Started $proc"); 6383 return $proc; 6384} 6385 6386sub create_debug_statement { 6387 my $run = shift; 6388 my $args= shift; 6389 my $input= shift; 6390 my @params_to_quote = ("--plugin_load=", "--plugin_load_add="); 6391 6392 # Put $args into a single string 6393 my $str= join(" ", @$$args); 6394 my $runline= $input ? "$run $str < $input" : "$run $str"; 6395 6396 foreach my $param_to_quote (@params_to_quote) { 6397 # add quotes to escape ; in plugin_load option 6398 my $pos1 = index($runline, $param_to_quote); 6399 if ( $pos1 != -1 ) { 6400 my $pos2 = index($runline, " ",$pos1); 6401 substr($runline,$pos1+length($param_to_quote),0) = "\""; 6402 substr($runline,$pos2+1,0) = "\""; 6403 } 6404 } 6405 6406 return $runline; 6407} 6408 6409# 6410# Modify the exe and args so that program is run in gdb in xterm 6411# 6412sub gdb_arguments { 6413 my $args= shift; 6414 my $exe= shift; 6415 my $type= shift; 6416 my $input= shift; 6417 6418 my $gdb_init_file= "$opt_vardir/tmp/gdbinit.$type"; 6419 6420 # Remove the old gdbinit file 6421 unlink($gdb_init_file); 6422 6423 my $runline=create_debug_statement("run", $args,$input); 6424 6425 # write init file for mysqld or client 6426 mtr_tofile($gdb_init_file, 6427 "break main\n" . 6428 $runline); 6429 6430 if ( $opt_manual_gdb ) 6431 { 6432 print "\nTo start gdb for $type, type in another window:\n"; 6433 print "gdb -cd $glob_mysql_test_dir -x $gdb_init_file $$exe\n"; 6434 6435 # Indicate the exe should not be started 6436 $$exe= undef; 6437 return; 6438 } 6439 6440 $$args= []; 6441 6442 my $term_exe; 6443 set_term_args($opt_mtr_term_args, $term_exe, $$args, $type); 6444 6445 if ( $exe_libtool ) 6446 { 6447 mtr_add_arg($$args, $exe_libtool); 6448 mtr_add_arg($$args, "--mode=execute"); 6449 } 6450 6451 mtr_add_arg($$args, "gdb"); 6452 mtr_add_arg($$args, "-x"); 6453 mtr_add_arg($$args, "$gdb_init_file"); 6454 mtr_add_arg($$args, "$$exe"); 6455 6456 $$exe= $term_exe; 6457} 6458 6459 # 6460# Modify the exe and args so that program is run in lldb 6461# 6462sub lldb_arguments { 6463 my $args= shift; 6464 my $exe= shift; 6465 my $type= shift; 6466 my $input= shift; 6467 6468 my $lldb_init_file= "$opt_vardir/tmp/lldbinit.$type"; 6469 unlink($lldb_init_file); 6470 6471 my $lldb_start_file= "$opt_vardir/tmp/lldbstart.$type"; 6472 unlink($lldb_start_file); 6473 6474 my $runline=create_debug_statement("process launch --", $args, $input); 6475 6476 # write init file for mysqld or client 6477 mtr_tofile($lldb_init_file, 6478 "b main\n" . 6479 $runline); 6480 6481 if ( $opt_manual_lldb ) 6482 { 6483 print "\nTo start lldb for $type, type in another window:\n"; 6484 print "cd $glob_mysql_test_dir && lldb -s $lldb_init_file $$exe\n"; 6485 6486 # Indicate the exe should not be started 6487 $$exe= undef; 6488 return; 6489 } 6490 6491 $$args= []; 6492 6493 my $term_exe; 6494 set_term_args($opt_mtr_term_args, $term_exe, $$args, $type); 6495 6496 mtr_add_arg($$args, $opt_lldb_cmd); 6497 mtr_add_arg($$args, "-s"); 6498 mtr_add_arg($$args, "$lldb_init_file"); 6499 mtr_add_arg($$args, "$$exe"); 6500 6501 $$exe= $term_exe; 6502} 6503 6504# 6505# Modify the exe and args so that program is run in ddd 6506# 6507sub ddd_arguments { 6508 my $args= shift; 6509 my $exe= shift; 6510 my $type= shift; 6511 my $input= shift; 6512 6513 my $gdb_init_file= "$opt_vardir/tmp/gdbinit.$type"; 6514 6515 # Remove the old gdbinit file 6516 unlink($gdb_init_file); 6517 6518 my $runline=create_debug_statement("run", $args,$input); 6519 6520 # write init file for mysqld or client 6521 mtr_tofile($gdb_init_file, 6522 "file $$exe\n" . 6523 "break main\n" . 6524 $runline); 6525 6526 if ( $opt_manual_ddd ) 6527 { 6528 print "\nTo start ddd for $type, type in another window:\n"; 6529 print "ddd -cd $glob_mysql_test_dir -x $gdb_init_file $$exe\n"; 6530 6531 # Indicate the exe should not be started 6532 $$exe= undef; 6533 return; 6534 } 6535 6536 my $save_exe= $$exe; 6537 $$args= []; 6538 if ( $exe_libtool ) 6539 { 6540 $$exe= $exe_libtool; 6541 mtr_add_arg($$args, "--mode=execute"); 6542 mtr_add_arg($$args, "ddd"); 6543 } 6544 else 6545 { 6546 $$exe= "ddd"; 6547 } 6548 mtr_add_arg($$args, "--command=$gdb_init_file"); 6549 mtr_add_arg($$args, "$save_exe"); 6550} 6551 6552 6553# 6554# Modify the exe and args so that program is run in dbx in xterm 6555# 6556sub dbx_arguments { 6557 my $args= shift; 6558 my $exe= shift; 6559 my $type= shift; 6560 my $input= shift; 6561 6562 # Put $args into a single string 6563 my $str= join " ", @$$args; 6564 my $runline= $input ? "run $str < $input" : "run $str"; 6565 6566 if ( $opt_manual_dbx ) { 6567 print "\nTo start dbx for $type, type in another window:\n"; 6568 print "cd $glob_mysql_test_dir; dbx -c \"stop in main; " . 6569 "$runline\" $$exe\n"; 6570 6571 # Indicate the exe should not be started 6572 $$exe= undef; 6573 return; 6574 } 6575 6576 $$args= []; 6577 mtr_add_arg($$args, "-title"); 6578 mtr_add_arg($$args, "$type"); 6579 mtr_add_arg($$args, "-e"); 6580 6581 if ( $exe_libtool ) { 6582 mtr_add_arg($$args, $exe_libtool); 6583 mtr_add_arg($$args, "--mode=execute"); 6584 } 6585 6586 mtr_add_arg($$args, "dbx"); 6587 mtr_add_arg($$args, "-c"); 6588 mtr_add_arg($$args, "stop in main; $runline"); 6589 mtr_add_arg($$args, "$$exe"); 6590 6591 $$exe= "xterm"; 6592} 6593 6594 6595# 6596# Modify the exe and args so that program is run in the selected debugger 6597# 6598sub debugger_arguments { 6599 my $args= shift; 6600 my $exe= shift; 6601 my $debugger= $opt_debugger || $opt_client_debugger; 6602 6603 if ( $debugger =~ /vcexpress|vc|devenv/ ) 6604 { 6605 # vc[express] /debugexe exe arg1 .. argn 6606 6607 # Add name of the exe and /debugexe before args 6608 unshift(@$$args, "$$exe"); 6609 unshift(@$$args, "/debugexe"); 6610 6611 # Set exe to debuggername 6612 $$exe= $debugger; 6613 6614 } 6615 elsif ( $debugger =~ /windbg/ ) 6616 { 6617 # windbg exe arg1 .. argn 6618 6619 # Add name of the exe before args 6620 unshift(@$$args, "$$exe"); 6621 6622 # Set exe to debuggername 6623 $$exe= $debugger; 6624 6625 } 6626 else 6627 { 6628 mtr_error("Unknown argument \"$debugger\" passed to --debugger"); 6629 } 6630} 6631 6632# 6633# Modify the exe and args so that program is run in strace 6634# 6635sub strace_server_arguments { 6636 my $args= shift; 6637 my $exe= shift; 6638 my $type= shift; 6639 6640 mtr_add_arg($args, "-o"); 6641 mtr_add_arg($args, "%s/log/%s.strace", $opt_vardir, $type); 6642 mtr_add_arg($args, "-f"); 6643 mtr_add_arg($args, $$exe); 6644 $$exe= "strace"; 6645} 6646 6647# 6648# Modify the exe and args so that program is run in valgrind 6649# 6650sub valgrind_arguments { 6651 my $args= shift; 6652 my $exe= shift; 6653 my $report_prefix= shift; 6654 6655 if (my @tool_list= grep(/^--tool=(memcheck|callgrind|helgrind|massif)/, @valgrind_args)) 6656 { 6657 # Get the value of the last specified --tool=<> argument to valgrind 6658 my ($tool_name)= $tool_list[-1] =~ /(memcheck|callgrind|helgrind|massif)$/; 6659 if ($tool_name=~ /memcheck/) 6660 { 6661 mtr_add_arg($args, "--leak-check=yes") ; 6662 # Support statically-linked malloc libraries and 6663 # dynamically-linked jemalloc 6664 mtr_add_arg($args, "--soname-synonyms=somalloc=NONE,somalloc=*jemalloc*"); 6665 } 6666 else 6667 { 6668 $$exe=~ /.*[\/](.*)$/; 6669 my $report_prefix= defined $report_prefix ? $report_prefix : $1; 6670 mtr_add_arg($args, "--$tool_name-out-file=$opt_vardir/log/". 6671 "$report_prefix"."_$tool_name.out.%%p"); 6672 } 6673 } 6674 6675 # Add valgrind options, can be overriden by user 6676 mtr_add_arg($args, '%s', $_) for (@valgrind_args); 6677 6678 mtr_add_arg($args, $$exe); 6679 6680 $$exe= $opt_valgrind_path || "valgrind"; 6681 6682 if ($exe_libtool) 6683 { 6684 # Add "libtool --mode-execute" before the test to execute 6685 # if running in valgrind(to avoid valgrinding bash) 6686 unshift(@$args, "--mode=execute", $$exe); 6687 $$exe= $exe_libtool; 6688 } 6689} 6690 6691# 6692# Search server logs for valgrind reports printed at mysqld termination 6693# 6694 6695sub valgrind_exit_reports() { 6696 my $aggregate= ''; 6697 6698 foreach my $log_file (keys %mysqld_logs) 6699 { 6700 my @culprits= (); 6701 my $valgrind_rep= ""; 6702 my $found_report= 0; 6703 my $err_in_report= 0; 6704 my $ignore_report= 0; 6705 6706 my $LOGF = IO::File->new($log_file) 6707 or mtr_error("Could not open file '$log_file' for reading: $!"); 6708 6709 while ( my $line = <$LOGF> ) 6710 { 6711 if ($line =~ /^CURRENT_TEST: (.+)$/) 6712 { 6713 my $testname= $1; 6714 # If we have a report, report it if needed and start new list of tests 6715 if ($found_report) 6716 { 6717 if ($err_in_report) 6718 { 6719 $aggregate.= "Valgrind report from $log_file after tests:\n"; 6720 $aggregate.= "@culprits\n$valgrind_rep\n"; 6721 $err_in_report= 0; 6722 } 6723 # Make ready to collect new report 6724 @culprits= (); 6725 $found_report= 0; 6726 $valgrind_rep= ""; 6727 } 6728 push (@culprits, $testname); 6729 next; 6730 } 6731 # This line marks a report to be ignored 6732 $ignore_report=1 if $line =~ /VALGRIND_DO_QUICK_LEAK_CHECK/; 6733 # This line marks the start of a valgrind report 6734 $found_report= 1 if $line =~ /^==\d+== .* SUMMARY:/; 6735 6736 if ($ignore_report && $found_report) { 6737 $ignore_report= 0; 6738 $found_report= 0; 6739 } 6740 6741 if ($found_report) { 6742 $line=~ s/^==\d+== //; 6743 $valgrind_rep .= $line; 6744 $err_in_report= 1 if $line =~ /ERROR SUMMARY: [1-9]/; 6745 $err_in_report= 1 if $line =~ /definitely lost: [1-9]/; 6746 $err_in_report= 1 if $line =~ /possibly lost: [1-9]/; 6747 $err_in_report= 1 if $line =~ /still reachable: [1-9]/; 6748 } 6749 6750 $found_report= 1 if $line =~ / \[Note\] .*: Shutdown complete$/; 6751 } 6752 6753 $LOGF= undef; 6754 6755 if ($err_in_report) { 6756 $aggregate.= "Valgrind report from $log_file after tests:\n"; 6757 $aggregate.= "@culprits\n$valgrind_rep\n"; 6758 } 6759 } 6760 6761 return $aggregate; 6762} 6763 6764sub run_ctest() { 6765 my $olddir= getcwd(); 6766 chdir ($bindir) or die ("Could not chdir to $bindir"); 6767 my $tinfo; 6768 my $no_ctest= (IS_WINDOWS) ? 256 : -1; 6769 my $ctest_vs= ""; 6770 6771 # Just ignore if not configured/built to run ctest 6772 if (! -f "CTestTestfile.cmake") { 6773 mtr_report("No unit tests found."); 6774 chdir($olddir); 6775 return; 6776 } 6777 6778 # Add vs-config option if needed 6779 $ctest_vs= "-C $opt_vs_config" if $opt_vs_config; 6780 6781 # Limit ctest execution time 6782 my $ctest_timeout= "--timeout @{[$opt_testcase_timeout * 60]}"; 6783 6784 # Request Valgrind for unit tests if former was requested for other tests. 6785 my $ctest_memcheck= $opt_valgrind_mysqld ? ' -T memcheck' : ''; 6786 6787 # Also silently ignore if we don't have ctest and didn't insist 6788 # Special override: also ignore in Pushbuild, some platforms may not have it 6789 # Now, run ctest and collect output 6790 $ENV{CTEST_OUTPUT_ON_FAILURE} = 1; 6791 my $ctest_out= `ctest $ctest_vs $ctest_timeout $ctest_memcheck 2>&1`; 6792 if ($? == $no_ctest && ($opt_ctest == -1 || defined $ENV{PB2WORKDIR})) { 6793 chdir($olddir); 6794 return; 6795 } 6796 6797 # Create minimalistic "test" for the reporting 6798 $tinfo = My::Test->new 6799 ( 6800 name => 'unit_tests', 6801 ); 6802 # Set dummy worker id to align report with normal tests 6803 $tinfo->{worker} = 0 if $opt_parallel > 1; 6804 6805 my $ctfail= 0; # Did ctest fail? 6806 if ($?) { 6807 $ctfail= 1; 6808 $tinfo->{result}= 'MTR_RES_FAILED'; 6809 $tinfo->{comment}= "ctest failed with exit code $?, see result below"; 6810 $ctest_out= "" unless $ctest_out; 6811 } 6812 my $ctfile= "$opt_vardir/ctest.log"; 6813 my $ctres= 0; # Did ctest produce report summary? 6814 6815 open (CTEST, " > $ctfile") or die ("Could not open output file $ctfile"); 6816 6817 $ctest_report .= $ctest_out if $opt_ctest_report; 6818 6819 # Put ctest output in log file, while analyzing results 6820 for (split ('\n', $ctest_out)) { 6821 print CTEST "$_\n"; 6822 if (/tests passed/) { 6823 $ctres= 1; 6824 $ctest_report .= "\nUnit tests: $_\n"; 6825 } 6826 if ( /FAILED/ or /\(Failed\)/ ) { 6827 $ctfail= 1; 6828 $ctest_report .= " $_\n"; 6829 } 6830 } 6831 close CTEST; 6832 6833 # Set needed 'attributes' for test reporting 6834 $tinfo->{comment}.= "\nctest did not pruduce report summary" if ! $ctres; 6835 $tinfo->{result}= ($ctres && !$ctfail) 6836 ? 'MTR_RES_PASSED' : 'MTR_RES_FAILED'; 6837 $ctest_report .= "Report from unit tests in $ctfile"; 6838 $tinfo->{failures}= ($tinfo->{result} eq 'MTR_RES_FAILED'); 6839 6840 $tinfo->{comment} .= "\n" . $ctest_out; 6841 mark_time_used('test'); 6842 mtr_report_test($tinfo); 6843 chdir($olddir); 6844 mtr_report_test_subunit($tinfo); 6845 return $tinfo; 6846} 6847 6848# 6849# Usage 6850# 6851sub usage ($) { 6852 my ($message)= @_; 6853 6854 if ( $message ) 6855 { 6856 print STDERR "$message\n"; 6857 } 6858 6859 print <<HERE; 6860 6861$0 [ OPTIONS ] [ TESTCASE ] 6862 6863Options to control what engine/variation to run 6864 6865 embedded-server Use the embedded server, i.e. no mysqld daemons 6866 ps-protocol Use the binary protocol between client and server 6867 cursor-protocol Use the cursor protocol between client and server 6868 (implies --ps-protocol) 6869 view-protocol Create a view to execute all non updating queries 6870 opt-trace-protocol Print optimizer trace 6871 explain-protocol Run 'EXPLAIN EXTENDED' on all SELECT, INSERT, 6872 REPLACE, UPDATE and DELETE queries. 6873 json-explain-protocol Run 'EXPLAIN FORMAT=JSON' on all SELECT, INSERT, 6874 REPLACE, UPDATE and DELETE queries. 6875 sp-protocol Create a stored procedure to execute all queries 6876 compress Use the compressed protocol between client and server 6877 ssl Use ssl protocol between client and server 6878 skip-ssl Dont start server with support for ssl connections 6879 vs-config Visual Studio configuration used to create executables 6880 (default: MTR_VS_CONFIG environment variable) 6881 6882 defaults-file=<config template> Use fixed config template for all 6883 tests 6884 defaults-extra-file=<config template> Extra config template to add to 6885 all generated configs 6886 combination=<opt> Use at least twice to run tests with specified 6887 options to mysqld 6888 skip-combinations Ignore combination file (or options) 6889 6890Options to control directories to use 6891 tmpdir=DIR The directory where temporary files are stored 6892 (default: ./var/tmp). 6893 vardir=DIR The directory where files generated from the test run 6894 is stored (default: ./var). Specifying a ramdisk or 6895 tmpfs will speed up tests. 6896 mem Run testsuite in "memory" using tmpfs or ramdisk 6897 Attempts to find a suitable location 6898 using a builtin list of standard locations 6899 for tmpfs (/dev/shm) 6900 The option can also be set using environment 6901 variable MTR_MEM=[DIR] 6902 clean-vardir Clean vardir if tests were successful and if 6903 running in "memory". Otherwise this option is ignored 6904 client-bindir=PATH Path to the directory where client binaries are located 6905 client-libdir=PATH Path to the directory where client libraries are located 6906 6907 6908Options to control what test suites or cases to run 6909 6910 force Continue to run the suite after failure 6911 with-ndbcluster-only Run only tests that include "ndb" in the filename 6912 skip-ndb[cluster] Skip all tests that need cluster. Default. 6913 include-ndb[cluster] Enable all tests that need cluster 6914 do-test=PREFIX or REGEX 6915 Run test cases which name are prefixed with PREFIX 6916 or fulfills REGEX 6917 skip-test=PREFIX or REGEX 6918 Skip test cases which name are prefixed with PREFIX 6919 or fulfills REGEX 6920 start-from=PREFIX Run test cases starting test prefixed with PREFIX where 6921 prefix may be suite.testname or just testname 6922 suite[s]=NAME1,..,NAMEN 6923 Collect tests in suites from the comma separated 6924 list of suite names. 6925 The default is: "$DEFAULT_SUITES" 6926 skip-rpl Skip the replication test cases. 6927 big-test Also run tests marked as "big" 6928 enable-disabled Run also tests marked as disabled 6929 print-testcases Don't run the tests but print details about all the 6930 selected tests, in the order they would be run. 6931 skip-test-list=FILE Skip the tests listed in FILE. Each line in the file 6932 is an entry and should be formatted as: 6933 <TESTNAME> : <COMMENT> 6934 6935Options that specify ports 6936 6937 mtr-port-base=# Base for port numbers, ports from this number to 6938 port-base=# number+9 are reserved. Should be divisible by 10; 6939 if not it will be rounded down. May be set with 6940 environment variable MTR_PORT_BASE. If this value is 6941 set and is not "auto", it overrides build-thread. 6942 mtr-build-thread=# Specify unique number to calculate port number(s) from. 6943 build-thread=# Can be set in environment variable MTR_BUILD_THREAD. 6944 Set MTR_BUILD_THREAD="auto" to automatically aquire 6945 a build thread id that is unique to current host 6946 6947Options for test case authoring 6948 6949 record TESTNAME (Re)genereate the result file for TESTNAME 6950 check-testcases Check testcases for sideeffects 6951 mark-progress Log line number and elapsed time to <testname>.progress 6952 6953Options that pass on options (these may be repeated) 6954 6955 mysqld=ARGS Specify additional arguments to "mysqld" 6956 mysqld-env=VAR=VAL Specify additional environment settings for "mysqld" 6957 6958Options to run test on running server 6959 6960 extern option=value Run only the tests against an already started server 6961 the options to use for connection to the extern server 6962 must be specified using name-value pair notation 6963 For example: 6964 ./$0 --extern socket=/tmp/mysqld.sock 6965 6966Options for debugging the product 6967 6968 boot-dbx Start bootstrap server in dbx 6969 boot-ddd Start bootstrap server in ddd 6970 boot-gdb Start bootstrap server in gdb 6971 client-dbx Start mysqltest client in dbx 6972 client-ddd Start mysqltest client in ddd 6973 client-debugger=NAME Start mysqltest in the selected debugger 6974 client-gdb Start mysqltest client in gdb 6975 dbx Start the mysqld(s) in dbx 6976 ddd Start the mysqld(s) in ddd 6977 debug Dump trace output for all servers and client programs 6978 debug-common Same as debug, but sets 'd' debug flags to 6979 "query,info,error,enter,exit"; you need this if you 6980 want both to see debug printouts and to use 6981 DBUG_EXECUTE_IF. 6982 debug-server Use debug version of server, but without turning on 6983 tracing 6984 debugger=NAME Start mysqld in the selected debugger 6985 gdb Start the mysqld(s) in gdb 6986 manual-debug Let user manually start mysqld in debugger, before 6987 running test(s) 6988 manual-gdb Let user manually start mysqld in gdb, before running 6989 test(s) 6990 manual-ddd Let user manually start mysqld in ddd, before running 6991 test(s) 6992 manual-dbx Let user manually start mysqld in dbx, before running 6993 test(s) 6994 lldb Start mysqld(s) in lldb 6995 manual-lldb Let user manually start mysqld in lldb, before running 6996 test(s) 6997 strace-client Create strace output for mysqltest client, 6998 strace-server Create strace output for mysqltest server, 6999 max-save-core Limit the number of core files saved (to avoid filling 7000 up disks for heavily crashing server). Defaults to 7001 $opt_max_save_core, set to 0 for no limit. Set 7002 it's default with MTR_MAX_SAVE_CORE 7003 max-save-datadir Limit the number of datadir saved (to avoid filling 7004 up disks for heavily crashing server). Defaults to 7005 $opt_max_save_datadir, set to 0 for no limit. Set 7006 it's default with MTR_MAX_SAVE_DATDIR 7007 max-test-fail Limit the number of test failurs before aborting 7008 the current test run. Defaults to 7009 $opt_max_test_fail, set to 0 for no limit. Set 7010 it's default with MTR_MAX_TEST_FAIL 7011 7012Environment variables controlling debugging parameters 7013 7014 MTR_TERM Configures the terminal command to run the debugger. 7015 Defaults to xterm, but most other visual terminals 7016 can also be specified. Examples: 7017 MTR_TERM="gnome-terminal --title %title% --wait -x" 7018 MTR_TERM="urxwt -title %title% -e" 7019 Note: older version of gnome-terminal did not support 7020 --wait - those versions aren't compatible. 7021 MTR_LLDB Configures the lldb executable when debugging with 7022 lldb, the default is "lldb". This is useful for 7023 using lldb on a non default path, or on distributions 7024 with versioned lldb binaries. Example: 7025 MTR_LLDB=lldb-8.0 7026 7027Options for valgrind 7028 7029 valgrind Run the "mysqltest" and "mysqld" executables using 7030 valgrind with default options 7031 valgrind-all Synonym for --valgrind 7032 valgrind-mysqltest Run the "mysqltest" and "mysql_client_test" executable 7033 with valgrind 7034 valgrind-mysqld Run the "mysqld" executable with valgrind 7035 valgrind-options=ARGS Deprecated, use --valgrind-option 7036 valgrind-option=ARGS Option to give valgrind, replaces default option(s), 7037 can be specified more then once 7038 valgrind-path=<EXE> Path to the valgrind executable 7039 callgrind Instruct valgrind to use callgrind 7040 helgrind Instruct valgrind to use helgrind 7041 7042Misc options 7043 user=USER User for connecting to mysqld(default: $opt_user) 7044 comment=STR Write STR to the output 7045 timer Show test case execution time. 7046 verbose More verbose output(use multiple times for even more) 7047 verbose-restart Write when and why servers are restarted 7048 start Only initialize and start the servers, using the 7049 startup settings for the first specified test case 7050 Example: 7051 $0 --start alias & 7052 start-and-exit Same as --start, but mysql-test-run terminates and 7053 leaves just the server running 7054 start-dirty Only start the servers (without initialization) for 7055 the first specified test case 7056 user-args In combination with start* and no test name, drops 7057 arguments to mysqld except those speficied with 7058 --mysqld (if any) 7059 wait-all If --start or --start-dirty option is used, wait for all 7060 servers to exit before finishing the process 7061 fast Run as fast as possible, dont't wait for servers 7062 to shutdown etc. 7063 force-restart Always restart servers between tests 7064 parallel=N Run tests in N parallel threads (default=1) 7065 Use parallel=auto for auto-setting of N 7066 repeat=N Run each test N number of times 7067 retry=N Retry tests that fail N times, limit number of failures 7068 to $opt_retry_failure 7069 retry-failure=N Limit number of retries for a failed test 7070 reorder Reorder tests to get fewer server restarts 7071 help Get this help text 7072 7073 testcase-timeout=MINUTES Max test case run time (default $opt_testcase_timeout) 7074 suite-timeout=MINUTES Max test suite run time (default $opt_suite_timeout) 7075 shutdown-timeout=SECONDS Max number of seconds to wait for server shutdown 7076 before killing servers (default $opt_shutdown_timeout) 7077 warnings Scan the log files for warnings. Use --nowarnings 7078 to turn off. 7079 7080 sleep=SECONDS Passed to mysqltest, will be used as fixed sleep time 7081 debug-sync-timeout=NUM Set default timeout for WAIT_FOR debug sync 7082 actions. Disable facility with NUM=0. 7083 gcov Collect coverage information after the test. 7084 The result is a gcov file per source and header file. 7085 gprof Collect profiling information using gprof. 7086 experimental=<file> Refer to list of tests considered experimental; 7087 failures will be marked exp-fail instead of fail. 7088 report-features First run a "test" that reports mysql features 7089 timestamp Print timestamp before each test report line 7090 timediff With --timestamp, also print time passed since 7091 *previous* test started 7092 max-connections=N Max number of open connection to server in mysqltest 7093 default-myisam Set default storage engine to MyISAM for non-innodb 7094 tests. This is needed after switching default storage 7095 engine to InnoDB. 7096 report-times Report how much time has been spent on different 7097 phases of test execution. 7098 nounit-tests Do not run unit tests. Normally run if configured 7099 and if not running named tests/suites 7100 unit-tests Run unit tests even if they would otherwise not be run 7101 unit-tests-report Include report of every test included in unit tests. 7102 stress=ARGS Run stress test, providing options to 7103 mysql-stress-test.pl. Options are separated by comma. 7104 junit-output=FILE Output JUnit test summary XML to FILE. 7105 junit-package=NAME Set the JUnit package name to NAME for this test run. 7106 7107Some options that control enabling a feature for normal test runs, 7108can be turned off by prepending 'no' to the option, e.g. --notimer. 7109This applies to reorder, timer, check-testcases and warnings. 7110 7111HERE 7112 exit(1); 7113 7114} 7115 7116sub list_options ($) { 7117 my $hash= shift; 7118 7119 for (keys %$hash) { 7120 s/([:=].*|[+!])$//; 7121 s/\|/\n--/g; 7122 print "--$_\n" unless /list-options/; 7123 } 7124 7125 exit(1); 7126} 7127 7128