mysql-test-run.pl 119 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4
#!/usr/bin/perl
# -*- cperl -*-

#
5 6 7
##############################################################################
#
#  mysql-test-run.pl
unknown's avatar
unknown committed
8
#
unknown's avatar
unknown committed
9
#  Tool used for executing a suite of .test files
unknown's avatar
unknown committed
10
#
11 12
#  See the "MySQL Test framework manual" for more information
#  http://dev.mysql.com/doc/mysqltest/en/index.html
unknown's avatar
unknown committed
13 14
#
#
15
##############################################################################
unknown's avatar
unknown committed
16

unknown's avatar
unknown committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
use strict;
use warnings;

BEGIN {
  # Check that mysql-test-run.pl is started from mysql-test/
  unless ( -f "mysql-test-run.pl" )
  {
    print "**** ERROR **** ",
      "You must start mysql-test-run from the mysql-test/ directory\n";
    exit(1);
  }
  # Check that lib exist
  unless ( -d "lib/" )
  {
    print "**** ERROR **** ",
      "Could not find the lib/ directory \n";
    exit(1);
  }
}
36

unknown's avatar
unknown committed
37

unknown's avatar
unknown committed
38
use lib "lib";
unknown's avatar
unknown committed
39 40
use Cwd;
use Getopt::Long;
unknown's avatar
unknown committed
41 42 43
use My::File::Path; # Patched version of File::Path
use File::Basename;
use File::Copy;
44
use File::Find;
unknown's avatar
unknown committed
45
use File::Temp qw / tempdir /;
46
use File::Spec::Functions qw / splitdir /;
unknown's avatar
unknown committed
47
use My::Platform;
unknown's avatar
unknown committed
48 49
use My::SafeProcess;
use My::ConfigFactory;
50
use My::Options;
unknown's avatar
unknown committed
51
use My::Find;
52
use My::SysInfo;
unknown's avatar
unknown committed
53
use mtr_cases;
54
use mtr_report;
55
use mtr_match;
56 57
use IO::Socket::INET;
use IO::Select;
58

unknown's avatar
unknown committed
59 60 61 62
require "lib/mtr_process.pl";
require "lib/mtr_io.pl";
require "lib/mtr_gcov.pl";
require "lib/mtr_misc.pl";
63
require "lib/mtr_unique.pl";
unknown's avatar
unknown committed
64

unknown's avatar
unknown committed
65
$SIG{INT}= sub { mtr_error("Got ^C signal"); };
unknown's avatar
unknown committed
66

unknown's avatar
unknown committed
67
our $mysql_version_id;
unknown's avatar
unknown committed
68 69
our $glob_mysql_test_dir;
our $basedir;
unknown's avatar
unknown committed
70 71 72

our $path_charsetsdir;
our $path_client_bindir;
unknown's avatar
unknown committed
73
our $path_client_libdir;
unknown's avatar
unknown committed
74
our $path_language;
75 76 77

our $path_current_testlog;
our $path_testlog;
unknown's avatar
unknown committed
78

unknown's avatar
unknown committed
79 80 81 82 83
our $default_vardir;
our $opt_vardir;                # Path to use for var/ dir
my $path_vardir_trace;          # unix formatted opt_vardir for trace files
my $opt_tmpdir;                 # Path to use for tmp/ dir
my $path_config_file;           # The generated config file, var/my.cnf
unknown's avatar
unknown committed
84

85 86 87 88 89 90
# Visual Studio produces executables in different sub-directories based on the
# configuration used to build them.  To make life easier, an environment
# variable or command-line option may be specified to control which set of
# executables will be used by the test suite.
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};

91
my $DEFAULT_SUITES= "main,binlog,federated,rpl,rpl_ndb,ndb";
92
my $opt_suites;
unknown's avatar
unknown committed
93

unknown's avatar
unknown committed
94
our $opt_verbose= 0;  # Verbose output, enable with --verbose
unknown's avatar
unknown committed
95 96 97 98

our $exe_mysql;
our $exe_mysqladmin;
our $exe_mysqltest;
99
our $exe_libtool;
unknown's avatar
unknown committed
100

101
my $opt_big_test= 0;
unknown's avatar
unknown committed
102

103
our @opt_combinations;
104

unknown's avatar
unknown committed
105
our @opt_extra_mysqld_opt;
unknown's avatar
unknown committed
106 107

our $opt_compress;
108 109 110 111
our $opt_ssl;
our $opt_skip_ssl;
our $opt_ssl_supported;
our $opt_ps_protocol;
112 113 114
our $opt_sp_protocol;
our $opt_cursor_protocol;
our $opt_view_protocol;
115

unknown's avatar
unknown committed
116
our $opt_debug;
unknown's avatar
unknown committed
117
our @opt_cases;                  # The test cases names in argv
118
our $opt_embedded_server;
119

unknown's avatar
unknown committed
120 121 122
# Options used when connecting to an already running server
my %opts_extern;
sub using_extern { return (keys %opts_extern > 0);};
123

unknown's avatar
unknown committed
124
our $opt_fast= 0;
unknown's avatar
unknown committed
125
our $opt_force;
126
our $opt_mem= $ENV{'MTR_MEM'};
unknown's avatar
unknown committed
127 128 129 130 131

our $opt_gcov;
our $opt_gcov_err;
our $opt_gcov_msg;

unknown's avatar
unknown committed
132
our $glob_debugger= 0;
unknown's avatar
unknown committed
133 134
our $opt_gdb;
our $opt_client_gdb;
unknown's avatar
unknown committed
135 136
our $opt_ddd;
our $opt_client_ddd;
unknown's avatar
unknown committed
137
our $opt_manual_gdb;
unknown's avatar
unknown committed
138 139
our $opt_manual_ddd;
our $opt_manual_debug;
140 141
our $opt_debugger;
our $opt_client_debugger;
unknown's avatar
unknown committed
142

unknown's avatar
unknown committed
143 144
my $config; # The currently running config
my $current_config_name; # The currently running config file template
unknown's avatar
unknown committed
145

unknown's avatar
unknown committed
146
my $opt_baseport;
147
my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto";
148

unknown's avatar
unknown committed
149
my $opt_record;
150
my $opt_report_features;
151
our $opt_check_testcases= 1;
unknown's avatar
unknown committed
152
my $opt_mark_progress;
unknown's avatar
unknown committed
153

unknown's avatar
unknown committed
154
my $opt_sleep;
unknown's avatar
unknown committed
155

156 157 158
my $opt_testcase_timeout=    15; # minutes
my $opt_suite_timeout   =   180; # minutes
my $opt_shutdown_timeout=    10; # seconds
Magnus Svensson's avatar
Magnus Svensson committed
159
my $opt_start_timeout   =   180; # seconds
unknown's avatar
unknown committed
160

unknown's avatar
unknown committed
161 162
my $opt_start;
my $opt_start_dirty;
unknown's avatar
unknown committed
163
my $opt_repeat= 1;
unknown's avatar
unknown committed
164
my $opt_retry= 3;
unknown's avatar
unknown committed
165
my $opt_retry_failure= 2;
unknown's avatar
unknown committed
166

167
my $opt_parallel;
unknown's avatar
unknown committed
168

unknown's avatar
unknown committed
169
my $opt_strace_client;
unknown's avatar
unknown committed
170

unknown's avatar
unknown committed
171
our $opt_user;
unknown's avatar
unknown committed
172

unknown's avatar
unknown committed
173 174 175 176 177 178 179 180 181
my $opt_valgrind= 0;
my $opt_valgrind_mysqld= 0;
my $opt_valgrind_mysqltest= 0;
my @default_valgrind_args= ("--show-reachable=yes");
my @valgrind_args;
my $opt_valgrind_path;
my $opt_callgrind;

our $opt_warnings= 1;
unknown's avatar
unknown committed
182

183 184
our $opt_skip_ndbcluster= 0;
our $opt_skip_ndbcluster_slave= 0;
185
our $opt_with_ndbcluster;
unknown's avatar
unknown committed
186

unknown's avatar
unknown committed
187 188 189
my $exe_ndbd;
my $exe_ndb_mgmd;
my $exe_ndb_waiter;
unknown's avatar
unknown committed
190

191 192
our $path_sql_dir;

unknown's avatar
unknown committed
193
our $debug_compiled_binaries;
194

195 196
our %mysqld_variables;

197 198
my $source_dist= 0;

199 200
my $opt_max_save_core= $ENV{MTR_MAX_SAVE_CORE} || 5;
my $opt_max_save_datadir= $ENV{MTR_MAX_SAVE_DATADIR} || 20;
201
my $opt_max_test_fail= $ENV{MTR_MAX_TEST_FAIL} || 10;
202

unknown's avatar
unknown committed
203 204
select(STDOUT);
$| = 1; # Automatically flush STDOUT
unknown's avatar
unknown committed
205 206 207

main();

208

unknown's avatar
unknown committed
209
sub main {
210
  report_option('verbose', 0);
unknown's avatar
unknown committed
211

212 213 214 215
  # This is needed for test log evaluation in "gen-build-status-page"
  # in all cases where the calling tool does not log the commands
  # directly before it executes them, like "make test-force-pl" in RPM builds.
  mtr_report("Logging: $0 ", join(" ", @ARGV));
216

217 218
  Getopt::Long::Configure("pass_through");
  GetOptions('parallel=i' => \$opt_parallel) or usage("Can't read options");
unknown's avatar
unknown committed
219

220 221 222
  if ( not defined $opt_parallel ) {
    # Try to find a suitable value for number of workers
    my $sys_info= My::SysInfo->new();
223

224 225 226 227 228 229
    $opt_parallel= $sys_info->num_cpus();
    for my $limit (2000, 1500, 1000, 500){
      $opt_parallel-- if ($sys_info->min_bogomips() < $limit);
    }
    $opt_parallel= 1 if ($opt_parallel < 1);
    mtr_report("Using parallel: $opt_parallel");
230
  }
231

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
  # Create server socket on any free port
  my $server = new IO::Socket::INET
    (
     LocalAddr => 'localhost',
     Proto => 'tcp',
     Listen => $opt_parallel,
    );
  mtr_error("Could not create testcase server port: $!") unless $server;
  my $server_port = $server->sockport();
  mtr_report("Using server port $server_port");

  # Create child processes
  my %children;
  for my $child_num (1..$opt_parallel){
    my $child_pid= My::SafeProcess::Base::_safe_fork();
    if ($child_pid == 0){
      $server= undef; # Close the server port in child
      run_worker($server_port, $child_num);
      exit(1);
    }
unknown's avatar
unknown committed
252

253 254
    $children{$child_pid}= 1;
  }
255

256
  command_line_setup(0);
unknown's avatar
unknown committed
257

258
  if ( $opt_gcov ) {
unknown's avatar
unknown committed
259 260 261
    gcov_prepare();
  }

262
  if (!$opt_suites) {
263 264 265 266 267 268 269 270 271 272 273 274 275
    $opt_suites= $DEFAULT_SUITES;

    # Check for any extra suites to enable based on the path name
    my %extra_suites=
      (
       "mysql-5.1-new-ndb"              => "ndb_team",
       "mysql-5.1-new-ndb-merge"        => "ndb_team",
       "mysql-5.1-telco-6.2"            => "ndb_team",
       "mysql-5.1-telco-6.2-merge"      => "ndb_team",
       "mysql-5.1-telco-6.3"            => "ndb_team",
       "mysql-6.0-ndb"                  => "ndb_team",
      );

276
    foreach my $dir ( reverse splitdir($basedir) ) {
277
      my $extra_suite= $extra_suites{$dir};
278
      if (defined $extra_suite) {
279 280 281 282 283 284 285
	mtr_report("Found extra suite: $extra_suite");
	$opt_suites= "$extra_suite,$opt_suites";
	last;
      }
    }
  }

unknown's avatar
unknown committed
286
  mtr_report("Collecting tests...");
287
  my $tests= collect_test_cases($opt_suites, \@opt_cases);
unknown's avatar
unknown committed
288

unknown's avatar
unknown committed
289 290
  if ( $opt_report_features ) {
    # Put "report features" as the first test to run
291 292 293 294 295 296 297 298
    my $tinfo = My::Test->new
      (
       name           => 'report_features',
       result_file    => undef, # Prints result
       path           => 'include/report-features.test'.
       master_opt     => [],
       slave_opt      => [],
      );
unknown's avatar
unknown committed
299
    unshift(@$tests, $tinfo);
unknown's avatar
unknown committed
300
  }
301

302 303 304 305 306 307
  initialize_servers();

  mtr_report();
  mtr_print_thick_line();
  mtr_print_header();

308
  my $num_tests= @$tests;
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
  my $completed= run_test_server($server, $tests, $opt_parallel);

  # Send Ctrl-C to any children still running
  kill("INT", keys(%children));

  # Wait for childs to exit
  foreach my $pid (keys %children)
  {
    my $ret_pid= waitpid($pid, 0);
    if ($ret_pid != $pid){
      mtr_report("Unknown process $ret_pid exited");
    }
    else {
      delete $children{$ret_pid};
    }
  }

unknown's avatar
unknown committed
326 327 328 329
  if ( not defined @$completed ) {
    mtr_error("Test suite aborted");
  }

330
  if ( @$completed != $num_tests){
331 332

    if ($opt_force){
333 334 335
      # All test should have been run, print any that are still in $tests
      foreach my $test ( @$tests ){
	$test->print_test();
336
      }
337 338
    }

339
    # Not all tests completed, failure
340
    mtr_report();
341 342
    mtr_report("Only ", int(@$completed), " of $num_tests completed.");
    mtr_error("Not all tests completed");
343 344
  }

345 346 347 348 349 350 351 352 353 354 355
  mtr_print_line();

  mtr_report_stats($completed);

  exit(0);
}


sub run_test_server {
  my ($server, $tests, $childs) = @_;

356 357
  my $num_saved_cores= 0;  # Number of core files saved in vardir/log/ so far.
  my $num_saved_datadir= 0;  # Number of datadirs saved in vardir/log/ so far.
358
  my $num_failed_test= 0; # Number of tests failed so far
359

360 361 362 363 364 365 366 367 368 369
  # Scheduler variables
  my $max_ndb= $opt_parallel / 2;
  $max_ndb = 4 if $max_ndb > 4;
  $max_ndb = 1 if $max_ndb < 1;
  my $num_ndb_tests= 0;

  my $completed= [];
  my %running;
  my $result;

unknown's avatar
unknown committed
370 371
  my $suite_timeout_proc= My::SafeProcess->timer($opt_suite_timeout * 60);

372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
  my $s= IO::Select->new();
  $s->add($server);
  while (1) {
    my @ready = $s->can_read(1); # Wake up once every second
    foreach my $sock (@ready) {
      if ($sock == $server) {
	# New client connected
	my $child= $sock->accept();
	mtr_verbose("Client connected");
	$s->add($child);
	print $child "HELLO\n";
      }
      else {
	my $line= <$sock>;
	if (!defined $line) {
	  # Client disconnected
	  mtr_verbose("Child closed socket");
	  $s->remove($sock);
	  if (--$childs == 0){
unknown's avatar
unknown committed
391
	    $suite_timeout_proc->kill();
392 393 394 395 396 397 398 399 400 401 402 403 404
	    return $completed;
	  }
	  next;
	}
	chomp($line);

	if ($line eq 'TESTRESULT'){
	  $result= My::Test::read_test($sock);
	  # $result->print_test();

	  # Report test status
	  mtr_report_test($result);

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
	  if ( $result->is_failed() ) {

	    # Save the workers "savedir" in var/log
	    my $worker_savedir= $result->{savedir};
	    my $worker_savename= basename($worker_savedir);
	    my $savedir= "$opt_vardir/log/$worker_savename";

	    if ($opt_max_save_datadir > 0 &&
		$num_saved_datadir >= $opt_max_save_datadir)
	    {
	      mtr_report(" - skipping '$worker_savedir/'");
	      rmtree($worker_savedir);
	    }
	    else {
	      mtr_report(" - saving '$worker_savedir/' to '$savedir/'");
	      rename($worker_savedir, $savedir);

422 423 424 425 426 427
	      if ($opt_max_save_core > 0) {
		# Limit number of core files saved
		find({ no_chdir => 1,
		       wanted => sub {
			 my $core_file= $File::Find::name;
			 my $core_name= basename($core_file);
428

429 430 431
			 if ($core_name =~ "core*"){
			   if ($num_saved_cores >= $opt_max_save_core) {
			     mtr_report(" - deleting '$core_name'",
432
				      "($num_saved_cores/$opt_max_save_core)");
433 434 435 436 437 438 439
			     unlink("$core_file");
			   }
			   else {
			     mtr_report(" - found '$core_name'",
				      "($num_saved_cores/$opt_max_save_core)");
			   }
			   ++$num_saved_cores;
440 441
			 }
		       }
442 443 444
		     },
		     $savedir);
	      }
445
	    }
446
	    $num_saved_datadir++;
447 448 449

	    if ( !$opt_force ) {
	      # Test has failed, force is off
unknown's avatar
unknown committed
450
	      $suite_timeout_proc->kill();
451 452 453
	      push(@$completed, $result);
	      return $completed;
	    }
454 455 456 457 458 459 460 461
	    elsif ($num_failed_test > 0 and
		   $num_failed_test >= $opt_max_test_fail) {
	      $suite_timeout_proc->kill();
	      mtr_report("Too many tests($num_failed_test) failed!",
			 "Terminating...");
	      return undef;
	    }
	    $num_failed_test++;
462 463 464
	  }

	  # Retry test run after test failure
unknown's avatar
unknown committed
465
	  my $retries= $result->{retries} || 2;
466
	  my $test_has_failed= $result->{failures} || 0;
unknown's avatar
unknown committed
467
	  if ($test_has_failed and $retries <= $opt_retry){
468 469 470 471
	    # Test should be run one more time unless it has failed
	    # too many times already
	    my $failures= $result->{failures};
	    if ($opt_retry > 1 and $failures >= $opt_retry_failure){
unknown's avatar
unknown committed
472
	      mtr_report("\nTest has failed $failures times,",
473 474 475 476
			 "no more retries!\n");
	    }
	    else {
	      mtr_report("\nRetrying test, attempt($retries/$opt_retry)...\n");
477
	      delete($result->{result});
478 479 480 481 482 483 484 485 486 487 488 489
	      $result->{retries}= $retries+1;
	      $result->write_test($sock, 'TESTCASE');
	      next;
	    }
	  }

	  # Repeat test $opt_repeat number of times
	  my $repeat= $result->{repeat} || 1;
	  if ($repeat < $opt_repeat)
	  {
	    $result->{retries}= 0;
	    $result->{failures}= 0;
490
	    delete($result->{result});
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
	    $result->{repeat}= $repeat+1;
	    $result->write_test($sock, 'TESTCASE');
	    next;
	  }

	  # Remove from list of running
	  mtr_error("'", $result->{name},"' is not known to be running")
	    unless delete $running{$result->key()};

	  # Update scheduler variables
	  $num_ndb_tests-- if ($result->{ndb_test});

	  # Save result in completed list
	  push(@$completed, $result);

	}
	elsif ($line eq 'START'){
	  ; # Send first test
	}
	else {
	  mtr_error("Unknown response: '$line' from client");
	}

	# Find next test to schedule
	# - Try to use same configuration as worker used last time
	# - Limit number of parallel ndb tests

	my $next;
	my $second_best;
	for(my $i= 0; $i <= $#$tests; $i++)
	{
	  my $t= $tests->[$i];

	  if (run_testcase_check_skip_test($t)){
	    # Move the test to completed list
	    #mtr_report("skip - Moving test $i to completed");
	    push(@$completed, splice(@$tests, $i, 1));
	    redo; # Start over again
	  }

	  # Limit number of parallell NDB tests
	  if ($t->{ndb_test} and $num_ndb_tests >= $max_ndb){
	    #mtr_report("Skipping, num ndb is already at max, $num_ndb_tests");
	    next;
	  }

	  # Prefer same configuration
	  if (defined $result and
	      $result->{template_path} eq $t->{template_path})
	  {
	    #mtr_report("Test uses same config => good match");
	    # Test uses same config => good match
	    $next= splice(@$tests, $i, 1);
	    last;
	  }

	  # Second best choice is the first that does not fulfill
	  # any of the above conditions
	  if (!defined $second_best){
	    #mtr_report("Setting second_best to $i");
	    $second_best= $i;
	  }
	}

	# Use second best choice if no other test has been found
	if (!$next and defined $second_best){
	  #mtr_report("Take second best choice $second_best");
	  mtr_error("Internal error, second best too large")
	    if $second_best >  $#$tests;
	  $next= splice(@$tests, $second_best, 1);
	}

	if ($next) {
	  #$next->print_test();
	  $next->write_test($sock, 'TESTCASE');
	  $running{$next->key()}= $next;
	  $num_ndb_tests++ if ($next->{ndb_test});
	}
	else {
	  # No more test, tell child to exit
	  #mtr_report("Saying BYE to child");
	  print $sock "BYE\n";
	}
      }
    }
unknown's avatar
unknown committed
576 577 578 579 580 581 582 583 584

    # ----------------------------------------------------
    # Check if test suite timer expired
    # ----------------------------------------------------
    if ( ! $suite_timeout_proc->wait_one(0) )
    {
      mtr_report("Test suite timeout! Terminating...");
      return undef;
    }
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
  }
}


sub run_worker ($) {
  my ($server_port, $thread_num)= @_;

  $SIG{INT}= sub { exit(1); };

  report_option('name',"worker[$thread_num]");

  # Connect to server
  my $server = new IO::Socket::INET
    (
     PeerAddr => 'localhost',
     PeerPort => $server_port,
     Proto    => 'tcp'
    );
  mtr_error("Could not connect to server at port $server_port: $!")
    unless $server;

  # Read hello from server which it will send when shared
  # resources have been setup
  my $hello= <$server>;

  command_line_setup($thread_num);

  if ( $opt_gcov )
  {
    gcov_prepare();
  }

  setup_vardir();
  mysql_install_db($thread_num);

unknown's avatar
unknown committed
620 621 622
  if ( using_extern() ) {
    create_config_file_for_extern(%opts_extern);
  }
unknown's avatar
unknown committed
623

624 625
  # Ask server for first test
  print $server "START\n";
unknown's avatar
unknown committed
626

627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
  while(my $line= <$server>){
    chomp($line);
    if ($line eq 'TESTCASE'){
      my $test= My::Test::read_test($server);
      #$test->print_test();
      run_testcase($test);
      #$test->{result}= 'MTR_RES_PASSED';
      # Send it back, now with results set
      #$test->print_test();
      $test->write_test($server, 'TESTRESULT');
    }
    elsif ($line eq 'BYE'){
      mtr_report("Server said BYE");
      exit(0);
    }
    else {
      mtr_error("Could not understand server, '$line'");
    }
  }

  stop_all_servers();

  if ( $opt_gcov )
  {
    gcov_collect(); # collect coverage information
  }

  if ( $opt_gcov )
  {
    gcov_collect(); # collect coverage information
  }

  exit(1);
unknown's avatar
unknown committed
660
}
unknown's avatar
unknown committed
661 662


unknown's avatar
unknown committed
663 664 665 666 667
sub ignore_option {
  my ($opt, $value)= @_;
  print "Ignoring option '$opt'\n";
}

unknown's avatar
unknown committed
668
sub command_line_setup {
669 670
  my ($thread_num)= @_;

unknown's avatar
unknown committed
671
  my $opt_comment;
unknown's avatar
unknown committed
672
  my $opt_usage;
unknown's avatar
unknown committed
673

unknown's avatar
unknown committed
674
  # Read the command line options
unknown's avatar
unknown committed
675
  # Note: Keep list, and the order, in sync with usage at end of this file
unknown's avatar
unknown committed
676
  Getopt::Long::Configure("pass_through");
unknown's avatar
unknown committed
677
  GetOptions(
unknown's avatar
unknown committed
678
             # Control what engine/variation to run
unknown's avatar
unknown committed
679
             'embedded-server'          => \$opt_embedded_server,
unknown's avatar
unknown committed
680
             'ps-protocol'              => \$opt_ps_protocol,
681 682 683
             'sp-protocol'              => \$opt_sp_protocol,
             'view-protocol'            => \$opt_view_protocol,
             'cursor-protocol'          => \$opt_cursor_protocol,
unknown's avatar
unknown committed
684
             'ssl|with-openssl'         => \$opt_ssl,
685 686
             'skip-ssl'                 => \$opt_skip_ssl,
             'compress'                 => \$opt_compress,
687
             'with-ndbcluster|ndb'      => \$opt_with_ndbcluster,
unknown's avatar
unknown committed
688 689 690 691 692 693
             'vs-config'                => \$opt_vs_config,

             # Config file to use as template for all tests
	     'defaults-file=s'          => \&collect_option,
	     # Extra config file to append to all generated configs
	     'defaults-extra-file=s'    => \&collect_option,
unknown's avatar
unknown committed
694 695

             # Control what test suites or cases to run
unknown's avatar
unknown committed
696
             'force'                    => \$opt_force,
unknown's avatar
unknown committed
697
             'with-ndbcluster-only'     => \&collect_option,
unknown's avatar
unknown committed
698
             'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
unknown's avatar
unknown committed
699 700
             'skip-ndbcluster-slave|skip-ndb-slave'
                                        => \$opt_skip_ndbcluster_slave,
701
             'suite|suites=s'           => \$opt_suites,
unknown's avatar
unknown committed
702 703 704 705
             'skip-rpl'                 => \&collect_option,
             'skip-test=s'              => \&collect_option,
             'do-test=s'                => \&collect_option,
             'start-from=s'             => \&collect_option,
706
             'big-test'                 => \$opt_big_test,
unknown's avatar
unknown committed
707
	     'combination=s'            => \@opt_combinations,
unknown's avatar
unknown committed
708
             'skip-combinations'        => \&collect_option,
unknown's avatar
unknown committed
709

unknown's avatar
unknown committed
710 711
	     'skip-im'                  => \&ignore_option,

unknown's avatar
unknown committed
712
             # Specify ports
713
	     'build-thread|mtr-build-thread=i' => \$opt_build_thread,
unknown's avatar
unknown committed
714 715 716

             # Test case authoring
             'record'                   => \$opt_record,
717
             'check-testcases!'         => \$opt_check_testcases,
718
             'mark-progress'            => \$opt_mark_progress,
unknown's avatar
unknown committed
719

720
             # Extra options used when starting mysqld
unknown's avatar
unknown committed
721
             'mysqld=s'                 => \@opt_extra_mysqld_opt,
unknown's avatar
unknown committed
722 723

             # Run test on running server
unknown's avatar
unknown committed
724
             'extern=s'                  => \%opts_extern, # Append to hash
unknown's avatar
unknown committed
725 726

             # Debugging
unknown's avatar
unknown committed
727
             'debug'                    => \$opt_debug,
unknown's avatar
unknown committed
728
             'gdb'                      => \$opt_gdb,
unknown's avatar
unknown committed
729
             'client-gdb'               => \$opt_client_gdb,
unknown's avatar
unknown committed
730 731
             'manual-gdb'               => \$opt_manual_gdb,
             'manual-debug'             => \$opt_manual_debug,
unknown's avatar
unknown committed
732
             'ddd'                      => \$opt_ddd,
unknown's avatar
unknown committed
733
             'client-ddd'               => \$opt_client_ddd,
unknown's avatar
unknown committed
734
             'manual-ddd'               => \$opt_manual_ddd,
735 736
	     'debugger=s'               => \$opt_debugger,
	     'client-debugger=s'        => \$opt_client_debugger,
unknown's avatar
unknown committed
737
             'strace-client:s'          => \$opt_strace_client,
738
             'max-save-core=i'          => \$opt_max_save_core,
739
             'max-save-datadir=i'       => \$opt_max_save_datadir,
740
             'max-test-fail=i'          => \$opt_max_test_fail,
unknown's avatar
unknown committed
741 742 743

             # Coverage, profiling etc
             'gcov'                     => \$opt_gcov,
744
             'valgrind|valgrind-all'    => \$opt_valgrind,
unknown's avatar
unknown committed
745 746
             'valgrind-mysqltest'       => \$opt_valgrind_mysqltest,
             'valgrind-mysqld'          => \$opt_valgrind_mysqld,
unknown's avatar
unknown committed
747 748 749 750 751 752 753 754 755 756 757 758
             'valgrind-options=s'       => sub {
	       my ($opt, $value)= @_;
	       # Deprecated option unless it's what we know pushbuild uses
	       if ($value eq "--gen-suppressions=all --show-reachable=yes") {
		 push(@valgrind_args, $_) for (split(' ', $value));
		 return;
	       }
	       die("--valgrind-options=s is deprecated. Use ",
		   "--valgrind-option=s, to be specified several",
		   " times if necessary");
	     },
             'valgrind-option=s'        => \@valgrind_args,
unknown's avatar
unknown committed
759
             'valgrind-path=s'          => \$opt_valgrind_path,
760
	     'callgrind'                => \$opt_callgrind,
unknown's avatar
unknown committed
761

762 763 764
	     # Directories
             'tmpdir=s'                 => \$opt_tmpdir,
             'vardir=s'                 => \$opt_vardir,
765
             'mem'                      => \$opt_mem,
unknown's avatar
unknown committed
766 767
             'client-bindir=s'          => \$path_client_bindir,
             'client-libdir=s'          => \$path_client_libdir,
768

unknown's avatar
unknown committed
769
             # Misc
770
             'report-features'          => \$opt_report_features,
unknown's avatar
unknown committed
771
             'comment=s'                => \$opt_comment,
unknown's avatar
unknown committed
772
             'fast'                     => \$opt_fast,
773
             'reorder!'                 => \&collect_option,
unknown's avatar
unknown committed
774 775
             'enable-disabled'          => \&collect_option,
             'verbose+'                 => \$opt_verbose,
776
             'verbose-restart'          => \&report_option,
unknown's avatar
unknown committed
777
             'sleep=i'                  => \$opt_sleep,
778
             'start-dirty'              => \$opt_start_dirty,
unknown's avatar
unknown committed
779 780
             'start'                    => \$opt_start,
	     'print-testcases'          => \&collect_option,
unknown's avatar
unknown committed
781 782 783
	     'repeat=i'                 => \$opt_repeat,
	     'retry=i'                  => \$opt_retry,
	     'retry-failure=i'          => \$opt_retry_failure,
unknown's avatar
unknown committed
784
             'timer!'                   => \&report_option,
unknown's avatar
unknown committed
785
             'user=s'                   => \$opt_user,
786 787
             'testcase-timeout=i'       => \$opt_testcase_timeout,
             'suite-timeout=i'          => \$opt_suite_timeout,
unknown's avatar
unknown committed
788 789
             'shutdown-timeout=i'       => \$opt_shutdown_timeout,
             'warnings!'                => \$opt_warnings,
790
	     'timestamp'                => \&report_option,
unknown's avatar
unknown committed
791
	     'timediff'                 => \&report_option,
unknown's avatar
unknown committed
792 793

             'help|h'                   => \$opt_usage,
unknown's avatar
unknown committed
794 795
            ) or usage("Can't read options");

unknown's avatar
unknown committed
796 797
  usage("") if $opt_usage;

unknown's avatar
unknown committed
798
  # --------------------------------------------------------------------------
799
  # Setup verbosity
unknown's avatar
unknown committed
800
  # --------------------------------------------------------------------------
801 802 803 804 805 806 807 808 809 810 811
  if ($thread_num == 0){
    # The server should by default have verbose on
    report_option('verbose', $opt_verbose ? $opt_verbose : 0);
  } else {
    # Worker should by default have verbose off
    report_option('verbose', $opt_verbose ? $opt_verbose : undef);
  }

  # --------------------------------------------------------------------------
  # Check build_thread and calculate baseport
  # Use auto build thread in all but first worker
unknown's avatar
unknown committed
812
  # --------------------------------------------------------------------------
813
  set_build_thread_ports($thread_num > 1 ? 'auto' : $opt_build_thread);
unknown's avatar
unknown committed
814

815 816
  if ( -d "../sql" )
  {
817
    $source_dist=  1;
818 819
  }

820
  # Find the absolute path to the test directory
unknown's avatar
unknown committed
821 822
  $glob_mysql_test_dir= cwd();
  if (IS_CYGWIN)
unknown's avatar
unknown committed
823
  {
unknown's avatar
unknown committed
824 825
    # Use mixed path format i.e c:/path/to/
    $glob_mysql_test_dir= mixed_path($glob_mysql_test_dir);
unknown's avatar
unknown committed
826
  }
827 828 829 830

  # In most cases, the base directory we find everything relative to,
  # is the parent directory of the "mysql-test" directory. For source
  # distributions, TAR binary distributions and some other packages.
unknown's avatar
unknown committed
831
  $basedir= dirname($glob_mysql_test_dir);
832 833 834 835 836 837

  # In the RPM case, binaries and libraries are installed in the
  # default system locations, instead of having our own private base
  # directory. And we install "/usr/share/mysql-test". Moving up one
  # more directory relative to "mysql-test" gives us a usable base
  # directory for RPM installs.
unknown's avatar
unknown committed
838
  if ( ! $source_dist and ! -d "$basedir/bin" )
839
  {
unknown's avatar
unknown committed
840
    $basedir= dirname($basedir);
841 842
  }

843
  # Look for the client binaries directory
unknown's avatar
unknown committed
844 845 846 847 848 849 850 851 852 853 854 855 856
  if ($path_client_bindir)
  {
    # --client-bindir=path set on command line, check that the path exists
    $path_client_bindir= mtr_path_exists($path_client_bindir);
  }
  else
  {
    $path_client_bindir= mtr_path_exists("$basedir/client_release",
					 "$basedir/client_debug",
					 vs_config_dirs('client', ''),
					 "$basedir/client",
					 "$basedir/bin");
  }
857

unknown's avatar
unknown committed
858
  # Look for language files and charsetsdir, use same share
unknown's avatar
unknown committed
859 860 861
  my $path_share=      mtr_path_exists("$basedir/share/mysql",
				       "$basedir/sql/share",
				       "$basedir/share");
unknown's avatar
unknown committed
862 863 864 865

  $path_language=      mtr_path_exists("$path_share/english");
  $path_charsetsdir=   mtr_path_exists("$path_share/charsets");

unknown's avatar
unknown committed
866 867
  # Look for SQL scripts directory
  if ( mtr_file_exists("$path_share/mysql_system_tables.sql") ne "")
unknown's avatar
unknown committed
868
  {
unknown's avatar
unknown committed
869 870
    # The SQL scripts are in path_share
    $path_sql_dir= $path_share;
unknown's avatar
unknown committed
871 872 873
  }
  else
  {
unknown's avatar
unknown committed
874 875
    $path_sql_dir= mtr_path_exists("$basedir/share",
				   "$basedir/scripts");
unknown's avatar
unknown committed
876
  }
unknown's avatar
unknown committed
877

878
  # Run the mysqld to find out what features are available
unknown's avatar
unknown committed
879 880
  collect_mysqld_features();

unknown's avatar
unknown committed
881
  if ( $opt_comment )
unknown's avatar
unknown committed
882
  {
unknown's avatar
unknown committed
883 884 885 886
    mtr_report();
    mtr_print_thick_line('#');
    mtr_report("# $opt_comment");
    mtr_print_thick_line('#');
unknown's avatar
unknown committed
887
  }
unknown's avatar
unknown committed
888

unknown's avatar
unknown committed
889 890 891 892 893 894
  foreach my $arg ( @ARGV )
  {
    if ( $arg =~ /^--skip-/ )
    {
      push(@opt_extra_mysqld_opt, $arg);
    }
895 896 897 898 899 900
    elsif ( $arg =~ /^--$/ )
    {
      # It is an effect of setting 'pass_through' in option processing
      # that the lone '--' separating options from arguments survives,
      # simply ignore it.
    }
unknown's avatar
unknown committed
901 902 903 904 905 906 907 908 909
    elsif ( $arg =~ /^-/ )
    {
      usage("Invalid option \"$arg\"");
    }
    else
    {
      push(@opt_cases, $arg);
    }
  }
unknown's avatar
unknown committed
910

911 912 913
  # --------------------------------------------------------------------------
  # Find out type of logging that are being used
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
914
  foreach my $arg ( @opt_extra_mysqld_opt )
915
  {
unknown's avatar
unknown committed
916
    if ( $arg =~ /binlog[-_]format=(\S+)/ )
917
    {
unknown's avatar
unknown committed
918 919 920
      # Save this for collect phase
      collect_option('binlog-format', $1);
      mtr_report("Using binlog format '$1'");
921
    }
922 923
  }

924 925 926 927 928 929 930 931

  # --------------------------------------------------------------------------
  # Find out default storage engine being used(if any)
  # --------------------------------------------------------------------------
  foreach my $arg ( @opt_extra_mysqld_opt )
  {
    if ( $arg =~ /default-storage-engine=(\S+)/ )
    {
unknown's avatar
unknown committed
932 933 934
      # Save this for collect phase
      collect_option('default-storage-engine', $1);
      mtr_report("Using default engine '$1'")
935 936 937
    }
  }

938
  # --------------------------------------------------------------------------
939
  # Check if we should speed up tests by trying to run on tmpfs
940
  # - Dont check in workers
941
  # --------------------------------------------------------------------------
942
  if ( defined $opt_mem and $thread_num == 0)
943 944 945 946 947 948
  {
    mtr_error("Can't use --mem and --vardir at the same time ")
      if $opt_vardir;
    mtr_error("Can't use --mem and --tmpdir at the same time ")
      if $opt_tmpdir;

949
    # Search through list of locations that are known
950
    # to be "fast disks" to find a suitable location
951 952 953
    # Use --mem=<dir> as first location to look.
    my @tmpfs_locations= ($opt_mem, "/dev/shm", "/tmp");

954 955 956 957
    foreach my $fs (@tmpfs_locations)
    {
      if ( -d $fs )
      {
958
	my $template= "var_${opt_build_thread}_XXXX";
959
	$opt_mem= tempdir( $template, DIR => $fs, CLEANUP => 0);
960 961 962 963
	last;
      }
    }
  }
964

965 966 967
  # --------------------------------------------------------------------------
  # Set the "var/" directory, as it is the base for everything else
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
968
  $default_vardir= "$glob_mysql_test_dir/var";
969 970
  if ( ! $opt_vardir )
  {
971
    $opt_vardir= $default_vardir;
972
  }
unknown's avatar
unknown committed
973

974 975 976 977
  # If more than one parallel run, use a subdir of the selected var
  if ($thread_num && $opt_parallel > 1) {
    $opt_vardir.= "/".$thread_num;
   }
unknown's avatar
unknown committed
978 979

  $path_vardir_trace= $opt_vardir;
unknown's avatar
unknown committed
980
  # Chop off any "c:", DBUG likes a unix path ex: c:/src/... => /src/...
unknown's avatar
unknown committed
981
  $path_vardir_trace=~ s/^\w://;
unknown's avatar
unknown committed
982

unknown's avatar
unknown committed
983 984
  # We make the path absolute, as the server will do a chdir() before usage
  unless ( $opt_vardir =~ m,^/, or
unknown's avatar
unknown committed
985
           (IS_WINDOWS and $opt_vardir =~ m,^[a-z]:/,i) )
986 987 988 989
  {
    # Make absolute path, relative test dir
    $opt_vardir= "$glob_mysql_test_dir/$opt_vardir";
  }
unknown's avatar
unknown committed
990

unknown's avatar
unknown committed
991 992 993
  # Location of my.cnf that all clients use
  $path_config_file= "$opt_vardir/my.cnf";

994
  # --------------------------------------------------------------------------
995
  # Set tmpdir
996 997
  # --------------------------------------------------------------------------
  $opt_tmpdir=       "$opt_vardir/tmp" unless $opt_tmpdir;
unknown's avatar
unknown committed
998
  $opt_tmpdir =~ s,/+$,,;       # Remove ending slash if any
unknown's avatar
unknown committed
999

1000
  # If more than one parallel run, use a subdir of the selected tmpdir
1001
  if ($thread_num && $opt_parallel > 1 and $opt_tmpdir ne "$opt_vardir/tmp") {
1002 1003 1004
    $opt_tmpdir.= "/".$thread_num;
   }

unknown's avatar
unknown committed
1005
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
1006
  # fast option
unknown's avatar
unknown committed
1007
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
1008 1009
  if ($opt_fast){
    $opt_shutdown_timeout= 0; # Kill processes instead of nice shutdown
unknown's avatar
unknown committed
1010 1011
  }

unknown's avatar
unknown committed
1012
  # --------------------------------------------------------------------------
1013
  # Record flag
unknown's avatar
unknown committed
1014
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
1015
  if ( $opt_record and ! @opt_cases )
unknown's avatar
unknown committed
1016 1017 1018 1019
  {
    mtr_error("Will not run in record mode without a specific test case");
  }

1020
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
1021
  # Embedded server flag
1022
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
1023
  if ( $opt_embedded_server )
unknown's avatar
unknown committed
1024
  {
unknown's avatar
unknown committed
1025
    if ( IS_WINDOWS )
unknown's avatar
unknown committed
1026 1027 1028 1029 1030
    {
      # Add the location for libmysqld.dll to the path.
      my $separator= ";";
      my $lib_mysqld=
        mtr_path_exists(vs_config_dirs('libmysqld',''));
unknown's avatar
unknown committed
1031
      if ( IS_CYGWIN )
unknown's avatar
unknown committed
1032
      {
unknown's avatar
unknown committed
1033
	$lib_mysqld= posix_path($lib_mysqld);
unknown's avatar
unknown committed
1034 1035 1036 1037 1038 1039
	$separator= ":";
      }
      $ENV{'PATH'}= "$ENV{'PATH'}".$separator.$lib_mysqld;
    }
    $opt_skip_ndbcluster= 1;       # Turn off use of NDB cluster
    $opt_skip_ssl= 1;              # Turn off use of SSL
unknown's avatar
unknown committed
1040

unknown's avatar
unknown committed
1041 1042 1043 1044 1045 1046 1047
    # Turn off use of bin log
    push(@opt_extra_mysqld_opt, "--skip-log-bin");

    if ( using_extern() )
    {
      mtr_error("Can't use --extern with --embedded-server");
    }
unknown's avatar
unknown committed
1048 1049
  }

1050
  # --------------------------------------------------------------------------
1051
  # Big test flags
1052
  # --------------------------------------------------------------------------
1053 1054 1055 1056
   if ( $opt_big_test )
   {
     $ENV{'BIG_TEST'}= 1;
   }
unknown's avatar
unknown committed
1057

1058 1059 1060
  # --------------------------------------------------------------------------
  # Gcov flag
  # --------------------------------------------------------------------------
1061
  if ( $opt_gcov and ! $source_dist )
unknown's avatar
unknown committed
1062
  {
unknown's avatar
unknown committed
1063 1064 1065
    mtr_error("Coverage test needs the source - please use source dist");
  }

1066
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
1067
  # Check debug related options
1068
  # --------------------------------------------------------------------------
1069
  if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd ||
1070 1071
       $opt_manual_gdb || $opt_manual_ddd || $opt_manual_debug ||
       $opt_debugger || $opt_client_debugger )
unknown's avatar
unknown committed
1072
  {
1073
    # Indicate that we are using debugger
unknown's avatar
unknown committed
1074
    $glob_debugger= 1;
unknown's avatar
unknown committed
1075
    if ( using_extern() )
unknown's avatar
unknown committed
1076
    {
unknown's avatar
unknown committed
1077
      mtr_error("Can't use --extern when using debugger");
unknown's avatar
unknown committed
1078 1079 1080
    }
  }

1081
  # --------------------------------------------------------------------------
1082 1083 1084 1085 1086
  # Set timeout values
  # --------------------------------------------------------------------------
  $opt_start_timeout*= $opt_parallel;

  #
1087
  # Check valgrind arguments
1088
  # --------------------------------------------------------------------------
unknown's avatar
unknown committed
1089
  if ( $opt_valgrind or $opt_valgrind_path or @valgrind_args)
unknown's avatar
unknown committed
1090
  {
unknown's avatar
unknown committed
1091 1092 1093 1094
    mtr_report("Turning on valgrind for all executables");
    $opt_valgrind= 1;
    $opt_valgrind_mysqld= 1;
    $opt_valgrind_mysqltest= 1;
unknown's avatar
unknown committed
1095 1096 1097 1098 1099 1100

    # Increase the timeouts when running with valgrind
    $opt_testcase_timeout*= 10;
    $opt_suite_timeout*= 6;
    $opt_start_timeout*= 10;

unknown's avatar
unknown committed
1101
  }
1102
  elsif ( $opt_valgrind_mysqld )
unknown's avatar
unknown committed
1103
  {
1104
    mtr_report("Turning on valgrind for mysqld(s) only");
unknown's avatar
unknown committed
1105
    $opt_valgrind= 1;
1106 1107 1108
  }
  elsif ( $opt_valgrind_mysqltest )
  {
1109
    mtr_report("Turning on valgrind for mysqltest and mysql_client_test only");
unknown's avatar
unknown committed
1110
    $opt_valgrind= 1;
1111 1112
  }

1113 1114 1115 1116 1117 1118 1119
  if ( $opt_callgrind )
  {
    mtr_report("Turning on valgrind with callgrind for mysqld(s)");
    $opt_valgrind= 1;
    $opt_valgrind_mysqld= 1;

    # Set special valgrind options unless options passed on command line
unknown's avatar
unknown committed
1120 1121
    push(@valgrind_args, "--trace-children=yes")
      unless @valgrind_args;
1122 1123
  }

1124 1125 1126
  if ( $opt_valgrind )
  {
    # Set valgrind_options to default unless already defined
unknown's avatar
unknown committed
1127 1128
    push(@valgrind_args, @default_valgrind_args)
      unless @valgrind_args;
unknown's avatar
unknown committed
1129

unknown's avatar
unknown committed
1130 1131
    mtr_report("Running valgrind with options \"",
	       join(" ", @valgrind_args), "\"");
unknown's avatar
unknown committed
1132
  }
unknown's avatar
unknown committed
1133

unknown's avatar
unknown committed
1134
  if ( ! $opt_user )
unknown's avatar
unknown committed
1135
  {
unknown's avatar
unknown committed
1136
    $opt_user= "root"; # We want to do FLUSH xxx commands
unknown's avatar
unknown committed
1137 1138
  }

1139 1140
  $path_testlog=         "$opt_vardir/log/mysqltest.log";
  $path_current_testlog= "$opt_vardir/log/current_test";
1141

1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
  mtr_report("Checking supported features...");

  check_ndbcluster_support(\%mysqld_variables);
  check_ssl_support(\%mysqld_variables);
  check_debug_support(\%mysqld_variables);

  executable_setup();

  environment_setup();

1152 1153
}

unknown's avatar
unknown committed
1154

1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
#
# To make it easier for different devs to work on the same host,
# an environment variable can be used to control all ports. A small
# number is to be used, 0 - 16 or similar.
#
# Note the MASTER_MYPORT has to be set the same in all 4.x and 5.x
# versions of this script, else a 4.0 test run might conflict with a
# 5.1 test run, even if different MTR_BUILD_THREAD is used. This means
# all port numbers might not be used in this version of the script.
#
# Also note the limitation of ports we are allowed to hand out. This
# differs between operating systems and configuration, see
# http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html
# But a fairly safe range seems to be 5001 - 32767
#
1170 1171
sub set_build_thread_ports($) {
  my $build_thread= shift || 0;
1172

1173 1174 1175
  if ( lc($build_thread) eq 'auto' ) {
    mtr_report("Requesting build thread... ");
    $build_thread=
unknown's avatar
unknown committed
1176
      mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299);
1177
    mtr_report(" - got $build_thread");
unknown's avatar
unknown committed
1178
  }
1179 1180
  $ENV{MTR_BUILD_THREAD}= $build_thread;
  $opt_build_thread= $build_thread;
unknown's avatar
unknown committed
1181

unknown's avatar
unknown committed
1182
  # Calculate baseport
1183
  $opt_baseport= $build_thread * 10 + 10000;
unknown's avatar
unknown committed
1184
  if ( $opt_baseport < 5001 or $opt_baseport + 9 >= 32767 )
1185 1186 1187
  {
    mtr_error("MTR_BUILD_THREAD number results in a port",
              "outside 5001 - 32767",
unknown's avatar
unknown committed
1188
              "($opt_baseport - $opt_baseport + 9)");
1189
  }
1190

1191
  mtr_report("Using MTR_BUILD_THREAD $build_thread,",
unknown's avatar
unknown committed
1192
	     "with reserved ports $opt_baseport..".($opt_baseport+9));
1193

unknown's avatar
unknown committed
1194 1195 1196
}


unknown's avatar
unknown committed
1197
sub collect_mysqld_features {
unknown's avatar
unknown committed
1198
  my $found_variable_list_start= 0;
1199 1200 1201 1202 1203 1204 1205
  my $use_tmpdir;
  if ( defined $opt_tmpdir and -d $opt_tmpdir){
    # Create the tempdir in $opt_tmpdir
    $use_tmpdir= $opt_tmpdir;
  }
  my $tmpdir= tempdir(CLEANUP => 0, # Directory removed by this function
		      DIR => $use_tmpdir);
1206

1207
  #
unknown's avatar
unknown committed
1208
  # Execute "mysqld --no-defaults --help --verbose" to get a
unknown's avatar
unknown committed
1209
  # list of all features and settings
1210
  #
1211 1212 1213
  # --no-defaults and --skip-grant-tables are to avoid loading
  # system-wide configs and plugins
  #
1214
  # --datadir must exist, mysqld will chdir into it
unknown's avatar
unknown committed
1215
  #
unknown's avatar
unknown committed
1216 1217 1218 1219 1220 1221 1222 1223 1224
  my $args;
  mtr_init_args(\$args);
  mtr_add_arg($args, "--no-defaults");
  mtr_add_arg($args, "--datadir=%s", mixed_path($tmpdir));
  mtr_add_arg($args, "--language=%s", $path_language);
  mtr_add_arg($args, "--skip-grant-tables");
  mtr_add_arg($args, "--verbose");
  mtr_add_arg($args, "--help");

1225
  my $exe_mysqld= find_mysqld($basedir);
unknown's avatar
unknown committed
1226 1227
  my $cmd= join(" ", $exe_mysqld, @$args);
  my $list= `$cmd`;
unknown's avatar
unknown committed
1228

1229
  foreach my $line (split('\n', $list))
unknown's avatar
unknown committed
1230
  {
unknown's avatar
unknown committed
1231 1232
    # First look for version
    if ( !$mysql_version_id )
unknown's avatar
unknown committed
1233
    {
unknown's avatar
unknown committed
1234
      # Look for version
1235 1236 1237
      my $exe_name= basename($exe_mysqld);
      mtr_verbose("exe_name: $exe_name");
      if ( $line =~ /^\S*$exe_name\s\sVer\s([0-9]*)\.([0-9]*)\.([0-9]*)/ )
unknown's avatar
unknown committed
1238
      {
1239
	#print "Major: $1 Minor: $2 Build: $3\n";
unknown's avatar
unknown committed
1240
	$mysql_version_id= $1*10000 + $2*100 + $3;
1241 1242
	#print "mysql_version_id: $mysql_version_id\n";
	mtr_report("MySQL Version $1.$2.$3");
unknown's avatar
unknown committed
1243
      }
unknown's avatar
unknown committed
1244 1245 1246
    }
    else
    {
unknown's avatar
unknown committed
1247
      if (!$found_variable_list_start)
unknown's avatar
unknown committed
1248
      {
unknown's avatar
unknown committed
1249
	# Look for start of variables list
1250
	if ( $line =~ /[\-]+\s[\-]+/ )
unknown's avatar
unknown committed
1251 1252 1253
	{
	  $found_variable_list_start= 1;
	}
1254 1255 1256
      }
      else
      {
unknown's avatar
unknown committed
1257
	# Put variables into hash
1258
	if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ )
unknown's avatar
unknown committed
1259
	{
1260
	  # print "$1=\"$2\"\n";
unknown's avatar
unknown committed
1261 1262
	  $mysqld_variables{$1}= $2;
	}
1263 1264
	else
	{
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277
	  # The variable list is ended with a blank line
	  if ( $line =~ /^[\s]*$/ )
	  {
	    last;
	  }
	  else
	  {
	    # Send out a warning, we should fix the variables that has no
	    # space between variable name and it's value
	    # or should it be fixed width column parsing? It does not
	    # look like that in function my_print_variables in my_getopt.c
	    mtr_warning("Could not parse variable list line : $line");
	  }
1278
	}
unknown's avatar
unknown committed
1279
      }
unknown's avatar
unknown committed
1280
    }
unknown's avatar
unknown committed
1281
  }
1282
  rmtree($tmpdir);
unknown's avatar
unknown committed
1283
  mtr_error("Could not find version of MySQL") unless $mysql_version_id;
1284
  mtr_error("Could not find variabes list") unless $found_variable_list_start;
unknown's avatar
unknown committed
1285 1286 1287 1288

}


1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
sub find_mysqld {
  my ($mysqld_basedir)= @_;

  my @mysqld_names= ("mysqld", "mysqld-max-nt", "mysqld-max",
		     "mysqld-nt");

  if ( $opt_debug ){
    # Put mysqld-debug first in the list of binaries to look for
    mtr_verbose("Adding mysqld-debug first in list of binaries to look for");
    unshift(@mysqld_names, "mysqld-debug");
  }

  return my_find_bin($mysqld_basedir,
		     ["sql", "libexec", "sbin"],
		     [@mysqld_names]);
}


unknown's avatar
unknown committed
1307 1308
sub executable_setup () {

1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
  #
  # Check if libtool is available in this distribution/clone
  # we need it when valgrinding or debugging non installed binary
  # Otherwise valgrind will valgrind the libtool wrapper or bash
  # and gdb will not find the real executable to debug
  #
  if ( -x "../libtool")
  {
    $exe_libtool= "../libtool";
    if ($opt_valgrind or $glob_debugger)
    {
      mtr_report("Using \"$exe_libtool\" when running valgrind or debugger");
    }
  }

unknown's avatar
unknown committed
1324 1325 1326
  # Look for the client binaries
  $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
  $exe_mysql=          mtr_exe_exists("$path_client_bindir/mysql");
unknown's avatar
unknown committed
1327

unknown's avatar
unknown committed
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
  if ( ! $opt_skip_ndbcluster )
  {
    $exe_ndbd=
      my_find_bin($basedir,
		  ["storage/ndb/src/kernel", "libexec"],
		  "ndbd");

    $exe_ndb_mgmd=
      my_find_bin($basedir,
		  ["storage/ndb/src/mgmsrv", "libexec"],
		  "ndb_mgmd");

    $exe_ndb_waiter=
      my_find_bin($basedir,
		  ["storage/ndb/tools/", "bin"],
		  "ndb_waiter");
1344

unknown's avatar
unknown committed
1345
  }
1346

unknown's avatar
unknown committed
1347
  # Look for mysqltest executable
unknown's avatar
unknown committed
1348
  if ( $opt_embedded_server )
unknown's avatar
unknown committed
1349
  {
unknown's avatar
unknown committed
1350
    $exe_mysqltest=
1351
      mtr_exe_exists(vs_config_dirs('libmysqld/examples','mysqltest_embedded'),
unknown's avatar
unknown committed
1352
                     "$basedir/libmysqld/examples/mysqltest_embedded",
1353
                     "$path_client_bindir/mysqltest_embedded");
unknown's avatar
unknown committed
1354
  }
unknown's avatar
unknown committed
1355 1356
  else
  {
1357
    $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
unknown's avatar
unknown committed
1358
  }
1359

unknown's avatar
unknown committed
1360 1361 1362
}


unknown's avatar
unknown committed
1363 1364 1365 1366 1367 1368 1369 1370
sub client_debug_arg($$) {
  my ($args, $client_name)= @_;

  if ( $opt_debug ) {
    mtr_add_arg($args,
		"--debug=d:t:A,%s/log/%s.trace",
		$path_vardir_trace, $client_name)
  }
1371 1372 1373
}


unknown's avatar
unknown committed
1374
sub mysql_fix_arguments () {
unknown's avatar
unknown committed
1375

unknown's avatar
unknown committed
1376
  return "" if ( IS_WINDOWS );
1377

unknown's avatar
unknown committed
1378 1379 1380
  my $exe=
    mtr_script_exists("$basedir/scripts/mysql_fix_privilege_tables",
		      "$path_client_bindir/mysql_fix_privilege_tables");
1381 1382
  my $args;
  mtr_init_args(\$args);
unknown's avatar
unknown committed
1383
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
1384

unknown's avatar
unknown committed
1385 1386 1387 1388 1389
  mtr_add_arg($args, "--basedir=", $basedir);
  mtr_add_arg($args, "--bindir=", $path_client_bindir);
  mtr_add_arg($args, "--verbose");
  return mtr_args2str($exe, @$args);
}
1390 1391


unknown's avatar
unknown committed
1392 1393 1394
sub client_arguments ($) {
  my $client_name= shift;
  my $client_exe= mtr_exe_exists("$path_client_bindir/$client_name");
1395

unknown's avatar
unknown committed
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
  my $args;
  mtr_init_args(\$args);
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  client_debug_arg($args, $client_name);
  return mtr_args2str($client_exe, @$args);
}


sub mysqlslap_arguments () {
  my $exe= mtr_exe_maybe_exists("$path_client_bindir/mysqlslap");
  if ( $exe eq "" ) {
    # mysqlap was not found

    if (defined $mysql_version_id and $mysql_version_id >= 50100 ) {
      mtr_error("Could not find the mysqlslap binary");
    }
    return ""; # Don't care about mysqlslap
1413 1414
  }

unknown's avatar
unknown committed
1415 1416 1417 1418 1419
  my $args;
  mtr_init_args(\$args);
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  client_debug_arg($args, "mysqlslap");
  return mtr_args2str($exe, @$args);
1420 1421
}

unknown's avatar
unknown committed
1422 1423 1424 1425

sub mysqldump_arguments ($) {
  my($group_suffix) = @_;
  my $exe= mtr_exe_exists("$path_client_bindir/mysqldump");
1426 1427 1428

  my $args;
  mtr_init_args(\$args);
unknown's avatar
unknown committed
1429
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
1430
  mtr_add_arg($args, "--defaults-group-suffix=%s", $group_suffix);
unknown's avatar
unknown committed
1431 1432 1433
  client_debug_arg($args, "mysqldump-$group_suffix");
  return mtr_args2str($exe, @$args);
}
1434 1435


unknown's avatar
unknown committed
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
sub mysql_client_test_arguments(){
  my $exe;
  # mysql_client_test executable may _not_ exist
  if ( $opt_embedded_server ) {
    $exe= mtr_exe_maybe_exists(
	    vs_config_dirs('libmysqld/examples','mysql_client_test_embedded'),
	    "$basedir/libmysqld/examples/mysql_client_test_embedded");
  } else {
    $exe= mtr_exe_maybe_exists(vs_config_dirs('tests', 'mysql_client_test'),
			       "$basedir/tests/mysql_client_test",
			       "$basedir/bin/mysql_client_test");
  }

  my $args;
  mtr_init_args(\$args);
  if ( $opt_valgrind_mysqltest ) {
    valgrind_arguments($args, \$exe);
1453
  }
unknown's avatar
unknown committed
1454 1455 1456 1457
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  mtr_add_arg($args, "--testcase");
  mtr_add_arg($args, "--vardir=$opt_vardir");
  client_debug_arg($args,"mysql_client_test");
1458

unknown's avatar
unknown committed
1459
  return mtr_args2str($exe, @$args);
1460 1461
}

unknown's avatar
unknown committed
1462

unknown's avatar
unknown committed
1463 1464 1465 1466 1467
#
# Set environment to be used by childs of this process for
# things that are constant during the whole lifetime of mysql-test-run
#
sub environment_setup {
unknown's avatar
unknown committed
1468

unknown's avatar
unknown committed
1469 1470
  umask(022);

1471
  my @ld_library_paths;
1472

unknown's avatar
unknown committed
1473
  if ($path_client_libdir)
unknown's avatar
unknown committed
1474
  {
unknown's avatar
unknown committed
1475 1476
    # Use the --client-libdir passed on commandline
    push(@ld_library_paths, "$path_client_libdir");
1477 1478
  }
  else
unknown's avatar
unknown committed
1479
  {
unknown's avatar
unknown committed
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
    # Setup LD_LIBRARY_PATH so the libraries from this distro/clone
    # are used in favor of the system installed ones
    if ( $source_dist )
    {
      push(@ld_library_paths, "$basedir/libmysql/.libs/",
	   "$basedir/libmysql_r/.libs/",
	   "$basedir/zlib.libs/");
    }
    else
    {
      push(@ld_library_paths, "$basedir/lib");
    }
1492 1493
  }

unknown's avatar
unknown committed
1494
  # --------------------------------------------------------------------------
1495 1496
  # Add the path where libndbclient can be found
  # --------------------------------------------------------------------------
1497
  if ( !$opt_skip_ndbcluster )
1498
  {
unknown's avatar
unknown committed
1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
    push(@ld_library_paths,  "$basedir/storage/ndb/src/.libs");
  }

  # --------------------------------------------------------------------------
  # Add the path where mysqld will find udf_example.so
  # --------------------------------------------------------------------------
  my $lib_udf_example=
    mtr_file_exists(vs_config_dirs('sql', 'udf_example.dll'),
		    "$basedir/sql/.libs/udf_example.so",);

  if ( $lib_udf_example )
  {
    push(@ld_library_paths, dirname($lib_udf_example));
  }

  $ENV{'UDF_EXAMPLE_LIB'}=
    ($lib_udf_example ? basename($lib_udf_example) : "");
1516 1517
  $ENV{'UDF_EXAMPLE_LIB_OPT'}= "--plugin-dir=".
    ($lib_udf_example ? dirname($lib_udf_example) : "");
unknown's avatar
unknown committed
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527

  # --------------------------------------------------------------------------
  # Add the path where mysqld will find ha_example.so
  # --------------------------------------------------------------------------
  if ($mysql_version_id >= 50100) {
    my $lib_example_plugin=
      mtr_file_exists(vs_config_dirs('storage/example', 'ha_example.dll'),
		      "$basedir/storage/example/.libs/ha_example.so",);
    $ENV{'EXAMPLE_PLUGIN'}=
      ($lib_example_plugin ? basename($lib_example_plugin) : "");
1528 1529 1530
    $ENV{'EXAMPLE_PLUGIN_OPT'}= "--plugin-dir=".
      ($lib_example_plugin ? dirname($lib_example_plugin) : "");

unknown's avatar
unknown committed
1531
  }
unknown's avatar
unknown committed
1532

1533
  # --------------------------------------------------------------------------
1534
  # Valgrind need to be run with debug libraries otherwise it's almost
1535 1536 1537
  # impossible to add correct supressions, that means if "/usr/lib/debug"
  # is available, it should be added to
  # LD_LIBRARY_PATH
1538 1539 1540 1541
  #
  # But pthread is broken in libc6-dbg on Debian <= 3.1 (see Debian
  # bug 399035, http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=399035),
  # so don't change LD_LIBRARY_PATH on that platform.
1542
  # --------------------------------------------------------------------------
1543
  my $debug_libraries_path= "/usr/lib/debug";
1544 1545 1546
  my $deb_version;
  if (  $opt_valgrind and -d $debug_libraries_path and
        (! -e '/etc/debian_version' or
unknown's avatar
unknown committed
1547 1548
	 ($deb_version=
	    mtr_grab_file('/etc/debian_version')) !~ /^[0-9]+\.[0-9]$/ or
1549
         $deb_version > 3.1 ) )
1550
  {
1551
    push(@ld_library_paths, $debug_libraries_path);
1552
  }
1553

1554
  $ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths,
unknown's avatar
unknown committed
1555
				$ENV{'LD_LIBRARY_PATH'} ?
1556
				split(':', $ENV{'LD_LIBRARY_PATH'}) : ());
1557 1558 1559
  mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}");

  $ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths,
1560 1561
				  $ENV{'DYLD_LIBRARY_PATH'} ?
				  split(':', $ENV{'DYLD_LIBRARY_PATH'}) : ());
1562
  mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}");
1563

1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574
  # The environment variable used for shared libs on AIX
  $ENV{'SHLIB_PATH'}= join(":", @ld_library_paths,
                           $ENV{'SHLIB_PATH'} ?
                           split(':', $ENV{'SHLIB_PATH'}) : ());
  mtr_debug("SHLIB_PATH: $ENV{'SHLIB_PATH'}");

  # The environment variable used for shared libs on hp-ux
  $ENV{'LIBPATH'}= join(":", @ld_library_paths,
                        $ENV{'LIBPATH'} ?
                        split(':', $ENV{'LIBPATH'}) : ());
  mtr_debug("LIBPATH: $ENV{'LIBPATH'}");
1575

1576
  $ENV{'CHARSETSDIR'}=              $path_charsetsdir;
unknown's avatar
unknown committed
1577 1578
  $ENV{'UMASK'}=              "0660"; # The octal *string*
  $ENV{'UMASK_DIR'}=          "0770"; # The octal *string*
unknown's avatar
unknown committed
1579

1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
  #
  # MySQL tests can produce output in various character sets
  # (especially, ctype_xxx.test). To avoid confusing Perl
  # with output which is incompatible with the current locale
  # settings, we reset the current values of LC_ALL and LC_CTYPE to "C".
  # For details, please see
  # Bug#27636 tests fails if LC_* variables set to *_*.UTF-8
  #
  $ENV{'LC_ALL'}=             "C";
  $ENV{'LC_CTYPE'}=           "C";
unknown's avatar
unknown committed
1590

unknown's avatar
unknown committed
1591
  $ENV{'LC_COLLATE'}=         "C";
unknown's avatar
unknown committed
1592
  $ENV{'USE_RUNNING_SERVER'}= using_extern();
unknown's avatar
unknown committed
1593
  $ENV{'MYSQL_TEST_DIR'}=     $glob_mysql_test_dir;
1594
  $ENV{'MYSQLTEST_VARDIR'}=   $opt_vardir;
unknown's avatar
unknown committed
1595
  $ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'master-port'} || 3306;
1596
  $ENV{'MYSQL_TMP_DIR'}=      $opt_tmpdir;
1597

1598 1599 1600
  # ----------------------------------------------------
  # Setup env for NDB
  # ----------------------------------------------------
unknown's avatar
unknown committed
1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624
  if ( ! $opt_skip_ndbcluster )
  {
    $ENV{'NDB_MGM'}=
      my_find_bin($basedir,
		  ["storage/ndb/src/mgmclient", "bin"],
		  "ndb_mgm");

    $ENV{'NDB_TOOLS_DIR'}=
      my_find_dir($basedir,
		  ["storage/ndb/tools", "bin"]);

    $ENV{'NDB_EXAMPLES_DIR'}=
      my_find_dir($basedir,
		  ["storage/ndb/ndbapi-examples", "bin"]);

    $ENV{'NDB_EXAMPLES_BINARY'}=
      my_find_bin($basedir,
		  ["storage/ndb/ndbapi-examples/ndbapi_simple", "bin"],
		  "ndbapi_simple", NOT_REQUIRED);

    my $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
    $ENV{'NDB_TOOLS_OUTPUT'}=         $path_ndb_testrun_log;
    $ENV{'NDB_EXAMPLES_OUTPUT'}=      $path_ndb_testrun_log;
  }
1625

1626
  # ----------------------------------------------------
unknown's avatar
unknown committed
1627
  # mysql clients
1628
  # ----------------------------------------------------
unknown's avatar
unknown committed
1629 1630 1631 1632 1633 1634 1635 1636 1637
  $ENV{'MYSQL_CHECK'}=              client_arguments("mysqlcheck");
  $ENV{'MYSQL_DUMP'}=               mysqldump_arguments(".1");
  $ENV{'MYSQL_DUMP_SLAVE'}=         mysqldump_arguments(".2");
  $ENV{'MYSQL_SLAP'}=               mysqlslap_arguments();
  $ENV{'MYSQL_IMPORT'}=             client_arguments("mysqlimport");
  $ENV{'MYSQL_SHOW'}=               client_arguments("mysqlshow");
  $ENV{'MYSQL_BINLOG'}=             client_arguments("mysqlbinlog");
  $ENV{'MYSQL'}=                    client_arguments("mysql");
  $ENV{'MYSQL_UPGRADE'}=            client_arguments("mysql_upgrade");
unknown's avatar
unknown committed
1638
  $ENV{'MYSQLADMIN'}=               native_path($exe_mysqladmin);
unknown's avatar
unknown committed
1639 1640 1641
  $ENV{'MYSQL_CLIENT_TEST'}=        mysql_client_test_arguments();
  $ENV{'MYSQL_FIX_SYSTEM_TABLES'}=  mysql_fix_arguments();
  $ENV{'EXE_MYSQL'}=                $exe_mysql;
1642

unknown's avatar
unknown committed
1643
  # ----------------------------------------------------
unknown's avatar
unknown committed
1644 1645
  # bug25714 executable may _not_ exist in
  # some versions, test using it should be skipped
1646
  # ----------------------------------------------------
unknown's avatar
unknown committed
1647 1648 1649
  my $exe_bug25714=
      mtr_exe_maybe_exists(vs_config_dirs('tests', 'bug25714'),
                           "$basedir/tests/bug25714");
unknown's avatar
unknown committed
1650
  $ENV{'MYSQL_BUG25714'}=  native_path($exe_bug25714);
1651

1652
  # ----------------------------------------------------
unknown's avatar
unknown committed
1653
  # mysql_fix_privilege_tables.sql
1654
  # ----------------------------------------------------
unknown's avatar
unknown committed
1655 1656 1657
  my $file_mysql_fix_privilege_tables=
    mtr_file_exists("$basedir/scripts/mysql_fix_privilege_tables.sql",
		    "$basedir/share/mysql_fix_privilege_tables.sql");
1658
  $ENV{'MYSQL_FIX_PRIVILEGE_TABLES'}=  $file_mysql_fix_privilege_tables;
1659 1660

  # ----------------------------------------------------
unknown's avatar
unknown committed
1661
  # my_print_defaults
1662
  # ----------------------------------------------------
unknown's avatar
unknown committed
1663 1664 1665 1666
  my $exe_my_print_defaults=
    mtr_exe_exists(vs_config_dirs('extra', 'my_print_defaults'),
		   "$path_client_bindir/my_print_defaults",
		   "$basedir/extra/my_print_defaults");
unknown's avatar
unknown committed
1667
  $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= native_path($exe_my_print_defaults);
1668

1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685

  # ----------------------------------------------------
  # Setup env so childs can execute myisampack and myisamchk
  # ----------------------------------------------------
  $ENV{'MYISAMCHK'}= native_path(mtr_exe_exists(
                       vs_config_dirs('storage/myisam', 'myisamchk'),
                       vs_config_dirs('myisam', 'myisamchk'),
                       "$path_client_bindir/myisamchk",
                       "$basedir/storage/myisam/myisamchk",
                       "$basedir/myisam/myisamchk"));
  $ENV{'MYISAMPACK'}= native_path(mtr_exe_exists(
                        vs_config_dirs('storage/myisam', 'myisampack'),
                        vs_config_dirs('myisam', 'myisampack'),
                        "$path_client_bindir/myisampack",
                        "$basedir/storage/myisam/myisampack",
                        "$basedir/myisam/myisampack"));

1686
  # ----------------------------------------------------
unknown's avatar
unknown committed
1687
  # perror
1688
  # ----------------------------------------------------
unknown's avatar
unknown committed
1689 1690 1691
  my $exe_perror= mtr_exe_exists(vs_config_dirs('extra', 'perror'),
				 "$basedir/extra/perror",
				 "$path_client_bindir/perror");
unknown's avatar
unknown committed
1692
  $ENV{'MY_PERROR'}= native_path($exe_perror);
1693

1694 1695 1696 1697
  # Create an environment variable to make it possible
  # to detect that valgrind is being used from test cases
  $ENV{'VALGRIND_TEST'}= $opt_valgrind;

unknown's avatar
unknown committed
1698 1699 1700
}


1701

1702 1703 1704 1705 1706
#
# Remove var and any directories in var/ created by previous
# tests
#
sub remove_stale_vardir () {
1707

unknown's avatar
unknown committed
1708
  mtr_report("Removing old var directory...");
unknown's avatar
unknown committed
1709

1710 1711
  # Safety!
  mtr_error("No, don't remove the vardir when running with --extern")
unknown's avatar
unknown committed
1712
    if using_extern();
1713 1714

  mtr_verbose("opt_vardir: $opt_vardir");
1715
  if ( $opt_vardir eq $default_vardir )
1716 1717 1718 1719
  {
    #
    # Running with "var" in mysql-test dir
    #
1720
    if ( -l $opt_vardir)
1721
    {
1722
      # var is a symlink
1723

1724
      if ( $opt_mem )
1725 1726
      {
	# Remove the directory which the link points at
1727
	mtr_verbose("Removing " . readlink($opt_vardir));
unknown's avatar
unknown committed
1728
	rmtree(readlink($opt_vardir));
1729

1730
	# Remove the "var" symlink
1731
	mtr_verbose("unlink($opt_vardir)");
1732
	unlink($opt_vardir);
1733 1734 1735 1736
      }
      else
      {
	# Some users creates a soft link in mysql-test/var to another area
1737 1738
	# - allow it, but remove all files in it

unknown's avatar
unknown committed
1739
	mtr_report(" - WARNING: Using the 'mysql-test/var' symlink");
1740

1741 1742 1743 1744
	# Make sure the directory where it points exist
	mtr_error("The destination for symlink $opt_vardir does not exist")
	  if ! -d readlink($opt_vardir);

1745 1746 1747
	foreach my $bin ( glob("$opt_vardir/*") )
	{
	  mtr_verbose("Removing bin $bin");
unknown's avatar
unknown committed
1748
	  rmtree($bin);
1749
	}
1750
      }
1751 1752 1753 1754
    }
    else
    {
      # Remove the entire "var" dir
1755
      mtr_verbose("Removing $opt_vardir/");
unknown's avatar
unknown committed
1756
      rmtree("$opt_vardir/");
1757
    }
1758 1759 1760 1761 1762 1763 1764

    if ( $opt_mem )
    {
      # A symlink from var/ to $opt_mem will be set up
      # remove the $opt_mem dir to assure the symlink
      # won't point at an old directory
      mtr_verbose("Removing $opt_mem");
unknown's avatar
unknown committed
1765
      rmtree($opt_mem);
1766 1767
    }

1768 1769 1770 1771 1772 1773 1774 1775 1776
  }
  else
  {
    #
    # Running with "var" in some other place
    #

    # Remove the var/ dir in mysql-test dir if any
    # this could be an old symlink that shouldn't be there
1777
    mtr_verbose("Removing $default_vardir");
unknown's avatar
unknown committed
1778
    rmtree($default_vardir);
1779 1780

    # Remove the "var" dir
1781
    mtr_verbose("Removing $opt_vardir/");
unknown's avatar
unknown committed
1782
    rmtree("$opt_vardir/");
1783
  }
1784 1785
}

unknown's avatar
unknown committed
1786 1787


1788 1789 1790 1791
#
# Create var and the directories needed in var
#
sub setup_vardir() {
1792
  mtr_report("Creating var directory '$opt_vardir'...");
unknown's avatar
unknown committed
1793

1794
  if ( $opt_vardir eq $default_vardir )
1795
  {
1796 1797 1798 1799 1800 1801
    #
    # Running with "var" in mysql-test dir
    #
    if ( -l $opt_vardir )
    {
      #  it's a symlink
1802

1803 1804 1805 1806 1807 1808 1809 1810 1811
      # Make sure the directory where it points exist
      mtr_error("The destination for symlink $opt_vardir does not exist")
	if ! -d readlink($opt_vardir);
    }
    elsif ( $opt_mem )
    {
      # Runinng with "var" as a link to some "memory" location, normally tmpfs
      mtr_verbose("Creating $opt_mem");
      mkpath($opt_mem);
1812

unknown's avatar
unknown committed
1813
      mtr_report(" - symlinking 'var' to '$opt_mem'");
1814 1815
      symlink($opt_mem, $opt_vardir);
    }
1816 1817
  }

1818 1819 1820 1821 1822
  if ( ! -d $opt_vardir )
  {
    mtr_verbose("Creating $opt_vardir");
    mkpath($opt_vardir);
  }
unknown's avatar
unknown committed
1823

1824 1825
  # Ensure a proper error message if vardir couldn't be created
  unless ( -d $opt_vardir and -w $opt_vardir )
1826
  {
1827 1828
    mtr_error("Writable 'var' directory is needed, use the " .
	      "'--vardir=<path>' option");
1829 1830
  }

1831 1832
  mkpath("$opt_vardir/log");
  mkpath("$opt_vardir/run");
1833

1834 1835 1836
  # Create var/tmp and tmp - they might be different
  mkpath("$opt_vardir/tmp");
  mkpath($opt_tmpdir) if ($opt_tmpdir ne "$opt_vardir/tmp");
unknown's avatar
unknown committed
1837

1838 1839 1840 1841 1842 1843 1844 1845 1846
  # On some operating systems, there is a limit to the length of a
  # UNIX domain socket's path far below PATH_MAX.
  # Don't allow that to happen
  if (check_socket_path_length("$opt_tmpdir/testsocket.sock")){
    mtr_error("Socket path '$opt_tmpdir' too long, it would be ",
	      "truncated and thus not possible to use for connection to ",
	      "MySQL Server. Set a shorter with --tmpdir=<path> option");
  }

unknown's avatar
unknown committed
1847 1848 1849
  # copy all files from std_data into var/std_data
  # and make them writable
  copytree("$glob_mysql_test_dir/std_data", "$opt_vardir/std_data");
unknown's avatar
unknown committed
1850 1851

  # Remove old log files
unknown's avatar
unknown committed
1852
  foreach my $name (glob("r/*.progress r/*.log r/*.warnings"))
unknown's avatar
unknown committed
1853 1854 1855
  {
    unlink($name);
  }
unknown's avatar
unknown committed
1856 1857 1858
}


unknown's avatar
unknown committed
1859 1860 1861 1862
#
# Check if running as root
# i.e a file can be read regardless what mode we set it to
#
1863
sub  check_running_as_root () {
1864
  my $test_file= "$opt_vardir/test_running_as_root.txt";
1865 1866 1867 1868 1869 1870 1871 1872 1873 1874
  mtr_tofile($test_file, "MySQL");
  chmod(oct("0000"), $test_file);

  my $result="";
  if (open(FILE,"<",$test_file))
  {
    $result= join('', <FILE>);
    close FILE;
  }

1875 1876 1877 1878
  # Some filesystems( for example CIFS) allows reading a file
  # although mode was set to 0000, but in that case a stat on
  # the file will not return 0000
  my $file_mode= (stat($test_file))[2] & 07777;
1879 1880

  $ENV{'MYSQL_TEST_ROOT'}= "NO";
1881 1882
  mtr_verbose("result: $result, file_mode: $file_mode");
  if ($result eq "MySQL" && $file_mode == 0)
1883 1884 1885 1886 1887
  {
    mtr_warning("running this script as _root_ will cause some " .
                "tests to be skipped");
    $ENV{'MYSQL_TEST_ROOT'}= "YES";
  }
1888 1889 1890

  chmod(oct("0755"), $test_file);
  unlink($test_file);
1891 1892 1893
}


unknown's avatar
unknown committed
1894 1895
sub check_ssl_support ($) {
  my $mysqld_variables= shift;
1896

unknown's avatar
unknown committed
1897
  if ($opt_skip_ssl)
1898
  {
unknown's avatar
unknown committed
1899
    mtr_report(" - skipping SSL");
1900 1901 1902 1903 1904
    $opt_ssl_supported= 0;
    $opt_ssl= 0;
    return;
  }

1905
  if ( ! $mysqld_variables->{'ssl'} )
1906 1907 1908 1909 1910 1911
  {
    if ( $opt_ssl)
    {
      mtr_error("Couldn't find support for SSL");
      return;
    }
unknown's avatar
unknown committed
1912
    mtr_report(" - skipping SSL, mysqld not compiled with SSL");
1913 1914 1915 1916
    $opt_ssl_supported= 0;
    $opt_ssl= 0;
    return;
  }
unknown's avatar
unknown committed
1917
  mtr_report(" - SSL connections supported");
1918 1919 1920 1921
  $opt_ssl_supported= 1;
}


unknown's avatar
unknown committed
1922 1923
sub check_debug_support ($) {
  my $mysqld_variables= shift;
unknown's avatar
unknown committed
1924

1925
  if ( ! $mysqld_variables->{'debug'} )
unknown's avatar
unknown committed
1926
  {
unknown's avatar
unknown committed
1927
    #mtr_report(" - binaries are not debug compiled");
unknown's avatar
unknown committed
1928
    $debug_compiled_binaries= 0;
1929 1930 1931 1932 1933

    if ( $opt_debug )
    {
      mtr_error("Can't use --debug, binaries does not support it");
    }
unknown's avatar
unknown committed
1934 1935
    return;
  }
unknown's avatar
unknown committed
1936
  mtr_report(" - binaries are debug compiled");
unknown's avatar
unknown committed
1937 1938 1939
  $debug_compiled_binaries= 1;
}

unknown's avatar
unknown committed
1940

1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
#
# Helper function to handle configuration-based subdirectories which Visual
# Studio uses for storing binaries.  If opt_vs_config is set, this returns
# a path based on that setting; if not, it returns paths for the default
# /release/ and /debug/ subdirectories.
#
# $exe can be undefined, if the directory itself will be used
#
sub vs_config_dirs ($$) {
  my ($path_part, $exe) = @_;

  $exe = "" if not defined $exe;

unknown's avatar
unknown committed
1954
  # Don't look in these dirs when not on windows
unknown's avatar
unknown committed
1955
  return () unless IS_WINDOWS;
unknown's avatar
unknown committed
1956

1957 1958
  if ($opt_vs_config)
  {
unknown's avatar
unknown committed
1959
    return ("$basedir/$path_part/$opt_vs_config/$exe");
1960 1961
  }

unknown's avatar
unknown committed
1962 1963 1964
  return ("$basedir/$path_part/release/$exe",
          "$basedir/$path_part/relwithdebinfo/$exe",
          "$basedir/$path_part/debug/$exe");
1965 1966
}

unknown's avatar
unknown committed
1967

unknown's avatar
unknown committed
1968 1969
sub check_ndbcluster_support ($) {
  my $mysqld_variables= shift;
1970

unknown's avatar
unknown committed
1971
  if ($opt_skip_ndbcluster)
1972
  {
unknown's avatar
unknown committed
1973
    mtr_report(" - skipping ndbcluster");
1974
    $opt_skip_ndbcluster_slave= $opt_skip_ndbcluster;
1975 1976
    return;
  }
1977

unknown's avatar
unknown committed
1978
  if ( ! $mysqld_variables{'ndb-connectstring'} )
1979
  {
unknown's avatar
unknown committed
1980
    mtr_report(" - skipping ndbcluster, mysqld not compiled with ndbcluster");
1981 1982
    $opt_skip_ndbcluster= 2;
    $opt_skip_ndbcluster_slave= 2;
1983
    return;
1984
  }
unknown's avatar
unknown committed
1985 1986

  mtr_report(" - using ndbcluster when necessary, mysqld supports it");
1987

unknown's avatar
unknown committed
1988
  return;
unknown's avatar
unknown committed
1989 1990
}

unknown's avatar
unknown committed
1991

1992
sub ndbcluster_wait_started($$){
unknown's avatar
unknown committed
1993
  my $cluster= shift;
1994
  my $ndb_waiter_extra_opt= shift;
unknown's avatar
unknown committed
1995
  my $path_waitlog= join('/', $opt_vardir, $cluster->name(), "ndb_waiter.log");
1996

unknown's avatar
unknown committed
1997
  my $args;
1998
  mtr_init_args(\$args);
unknown's avatar
unknown committed
1999 2000
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix());
2001
  mtr_add_arg($args, "--timeout=%d", $opt_start_timeout);
2002 2003 2004 2005 2006

  if ($ndb_waiter_extra_opt)
  {
    mtr_add_arg($args, "$ndb_waiter_extra_opt");
  }
unknown's avatar
unknown committed
2007 2008 2009 2010

  # Start the ndb_waiter which will connect to the ndb_mgmd
  # and poll it for state of the ndbd's, will return when
  # all nodes in the cluster is started
unknown's avatar
unknown committed
2011

unknown's avatar
unknown committed
2012 2013 2014 2015 2016 2017 2018 2019 2020
  my $res= My::SafeProcess->run
    (
     name          => "ndb_waiter ".$cluster->name(),
     path          => $exe_ndb_waiter,
     args          => \$args,
     output        => $path_waitlog,
     error         => $path_waitlog,
     append        => 1,
    );
2021

unknown's avatar
unknown committed
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
  # Check that ndb_mgmd(s) are still alive
  foreach my $ndb_mgmd ( in_cluster($cluster, ndb_mgmds()) )
  {
    my $proc= $ndb_mgmd->{proc};
    if ( ! $proc->wait_one(0) )
    {
      mtr_warning("$proc died");
      return 2;
    }
  }
2032

unknown's avatar
unknown committed
2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043
  # Check that all started ndbd(s) are still alive
  foreach my $ndbd ( in_cluster($cluster, ndbds()) )
  {
    my $proc= $ndbd->{proc};
    next unless defined $proc;
    if ( ! $proc->wait_one(0) )
    {
      mtr_warning("$proc died");
      return 3;
    }
  }
2044

unknown's avatar
unknown committed
2045
  if ($res)
2046
  {
unknown's avatar
unknown committed
2047
    mtr_verbose("ndbcluster_wait_started failed");
2048 2049 2050
    return 1;
  }
  return 0;
unknown's avatar
unknown committed
2051 2052 2053
}


2054 2055 2056 2057
sub ndb_mgmd_wait_started($) {
  my ($cluster)= @_;

  my $retries= 100;
unknown's avatar
unknown committed
2058
  while ($retries)
2059
  {
unknown's avatar
unknown committed
2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071
    my $result= ndbcluster_wait_started($cluster, "--no-contact");
    if ($result == 0)
    {
      # ndb_mgmd is started
      mtr_verbose("ndb_mgmd is started");
      return 0;
    }
    elsif ($result > 1)
    {
      mtr_warning("Cluster process failed while waiting for start");
      return $result;
    }
2072

unknown's avatar
unknown committed
2073
    mtr_milli_sleep(100);
2074 2075 2076
    $retries--;
  }

unknown's avatar
unknown committed
2077
  return 1;
2078 2079
}

unknown's avatar
unknown committed
2080

unknown's avatar
unknown committed
2081 2082
sub ndb_mgmd_start ($$) {
  my ($cluster, $ndb_mgmd)= @_;
unknown's avatar
unknown committed
2083

unknown's avatar
unknown committed
2084 2085 2086 2087 2088 2089
  mtr_verbose("ndb_mgmd_start");

  my $dir= $ndb_mgmd->value("DataDir");
  mkpath($dir) unless -d $dir;

  my $args;
unknown's avatar
unknown committed
2090
  mtr_init_args(\$args);
unknown's avatar
unknown committed
2091 2092 2093
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix());
  mtr_add_arg($args, "--mycnf");
2094
  mtr_add_arg($args, "--nodaemon");
unknown's avatar
unknown committed
2095

unknown's avatar
unknown committed
2096
  my $path_ndb_mgmd_log= "$dir/ndb_mgmd.log";
unknown's avatar
unknown committed
2097

unknown's avatar
unknown committed
2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
  $ndb_mgmd->{'proc'}= My::SafeProcess->new
    (
     name          => $ndb_mgmd->after('cluster_config.'),
     path          => $exe_ndb_mgmd,
     args          => \$args,
     output        => $path_ndb_mgmd_log,
     error         => $path_ndb_mgmd_log,
     append        => 1,
     verbose       => $opt_verbose,
    );
  mtr_verbose("Started $ndb_mgmd->{proc}");
unknown's avatar
unknown committed
2109

2110 2111 2112
  # FIXME Should not be needed
  # Unfortunately the cluster nodes will fail to start
  # if ndb_mgmd has not started properly
2113
  if (ndb_mgmd_wait_started($cluster))
2114
  {
unknown's avatar
unknown committed
2115 2116
    mtr_warning("Failed to wait for start of ndb_mgmd");
    return 1;
2117
  }
2118

unknown's avatar
unknown committed
2119
  return 0;
unknown's avatar
unknown committed
2120 2121 2122
}


unknown's avatar
unknown committed
2123 2124 2125 2126
sub ndbd_start {
  my ($cluster, $ndbd)= @_;

  mtr_verbose("ndbd_start");
unknown's avatar
unknown committed
2127

unknown's avatar
unknown committed
2128 2129
  my $dir= $ndbd->value("DataDir");
  mkpath($dir) unless -d $dir;
unknown's avatar
unknown committed
2130

unknown's avatar
unknown committed
2131
  my $args;
unknown's avatar
unknown committed
2132
  mtr_init_args(\$args);
unknown's avatar
unknown committed
2133 2134
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix());
unknown's avatar
unknown committed
2135 2136
  mtr_add_arg($args, "--nodaemon");

unknown's avatar
unknown committed
2137
# > 5.0 { 'character-sets-dir' => \&fix_charset_dir },
unknown's avatar
unknown committed
2138 2139


unknown's avatar
unknown committed
2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151
  my $path_ndbd_log= "$dir/ndbd.log";
  my $proc= My::SafeProcess->new
    (
     name          => $ndbd->after('cluster_config.'),
     path          => $exe_ndbd,
     args          => \$args,
     output        => $path_ndbd_log,
     error         => $path_ndbd_log,
     append        => 1,
     verbose       => $opt_verbose,
    );
  mtr_verbose("Started $proc");
2152

unknown's avatar
unknown committed
2153
  $ndbd->{proc}= $proc;
unknown's avatar
unknown committed
2154

unknown's avatar
unknown committed
2155
  return;
unknown's avatar
unknown committed
2156 2157 2158
}


unknown's avatar
unknown committed
2159
sub ndbcluster_start ($) {
unknown's avatar
unknown committed
2160 2161
  my $cluster= shift;

unknown's avatar
unknown committed
2162
  mtr_verbose("ndbcluster_start '".$cluster->name()."'");
unknown's avatar
unknown committed
2163

unknown's avatar
unknown committed
2164
  foreach my $ndb_mgmd ( in_cluster($cluster, ndb_mgmds()) )
2165
  {
unknown's avatar
unknown committed
2166 2167
    next if started($ndb_mgmd);
    ndb_mgmd_start($cluster, $ndb_mgmd);
2168 2169
  }

unknown's avatar
unknown committed
2170
  foreach my $ndbd ( in_cluster($cluster, ndbds()) )
unknown's avatar
unknown committed
2171
  {
unknown's avatar
unknown committed
2172 2173
    next if started($ndbd);
    ndbd_start($cluster, $ndbd);
unknown's avatar
unknown committed
2174 2175
  }

unknown's avatar
unknown committed
2176 2177 2178 2179
  return 0;
}


unknown's avatar
unknown committed
2180 2181 2182 2183 2184 2185 2186 2187 2188
sub create_config_file_for_extern {
  my %opts=
    (
     socket     => '/tmp/mysqld.sock',
     port       => 3306,
     user       => 'test',
     password   => '',
     @_
    );
unknown's avatar
unknown committed
2189

unknown's avatar
unknown committed
2190 2191 2192 2193 2194 2195 2196 2197
  mtr_report("Creating my.cnf file for extern server...");
  my $F= IO::File->new($path_config_file, "w")
    or mtr_error("Can't write to $path_config_file: $!");

  print $F "[client]\n";
  while (my ($option, $value)= each( %opts )) {
    print $F "$option= $value\n";
    mtr_report(" $option= $value");
unknown's avatar
unknown committed
2198 2199
  }

unknown's avatar
unknown committed
2200
  print $F <<EOF
unknown's avatar
unknown committed
2201

unknown's avatar
unknown committed
2202 2203 2204
# binlog reads from [client] and [mysqlbinlog]
[mysqlbinlog]
character-sets-dir= $path_charsetsdir
unknown's avatar
unknown committed
2205

unknown's avatar
unknown committed
2206 2207 2208 2209 2210 2211
# mysql_fix_privilege_tables.sh don't read from [client]
[mysql_fix_privilege_tables]
socket            = $opts{'socket'}
port              = $opts{'port'}
user              = $opts{'user'}
password          = $opts{'password'}
unknown's avatar
unknown committed
2212

unknown's avatar
unknown committed
2213

unknown's avatar
unknown committed
2214 2215
EOF
;
2216

unknown's avatar
unknown committed
2217 2218
  $F= undef; # Close file
}
2219

unknown's avatar
unknown committed
2220

unknown's avatar
unknown committed
2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235
#
# Kill processes left from previous runs, normally
# there should be none so make sure to warn
# if there is one
#
sub kill_leftovers ($) {
  my $rundir= shift;
  return unless ( -d $rundir );

  mtr_report("Checking leftover processes...");

  # Scan the "run" directory for process id's to kill
  opendir(RUNDIR, $rundir)
    or mtr_error("kill_leftovers, can't open dir \"$rundir\": $!");
  while ( my $elem= readdir(RUNDIR) )
unknown's avatar
unknown committed
2236
  {
unknown's avatar
unknown committed
2237 2238
    # Only read pid from files that end with .pid
    if ( $elem =~ /.*[.]pid$/ )
2239
    {
unknown's avatar
unknown committed
2240 2241 2242 2243 2244 2245 2246 2247 2248 2249
      my $pidfile= "$rundir/$elem";
      next unless -f $pidfile;
      my $pid= mtr_fromfile($pidfile);
      unlink($pidfile);
      unless ($pid=~ /^(\d+)/){
	# The pid was not a valid number
	mtr_warning("Got invalid pid '$pid' from '$elem'");
	next;
      }
      mtr_report(" - found old pid $pid in '$elem', killing it...");
unknown's avatar
unknown committed
2250

unknown's avatar
unknown committed
2251 2252 2253 2254 2255
      my $ret= kill(9, $pid);
      if ($ret == 0) {
	mtr_report("   process did not exist!");
	next;
      }
unknown's avatar
unknown committed
2256

unknown's avatar
unknown committed
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268
      my $check_counter= 100;
      while ($ret > 0 and $check_counter--) {
	mtr_milli_sleep(100);
	$ret= kill(0, $pid);
      }
      mtr_report($check_counter ? "   ok!" : "   failed!");
    }
    else
    {
      mtr_warning("Found non pid file '$elem' in '$rundir'")
	if -f "$rundir/$elem";
    }
unknown's avatar
unknown committed
2269
  }
unknown's avatar
unknown committed
2270 2271
  closedir(RUNDIR);
}
unknown's avatar
unknown committed
2272

unknown's avatar
unknown committed
2273 2274 2275 2276 2277 2278 2279 2280 2281
#
# Check that all the ports that are going to
# be used are free
#
sub check_ports_free
{
  my @ports_to_check;
  for ($opt_baseport..$opt_baseport+9){
    push(@ports_to_check, $_);
unknown's avatar
unknown committed
2282
  }
unknown's avatar
unknown committed
2283 2284 2285 2286 2287 2288 2289
  mtr_report("Checking ports...");
  # print "@ports_to_check\n";
  foreach my $port (@ports_to_check){
    if (mtr_ping_port($port)){
      mtr_report(" - 'localhost:$port' was not free");
      return 1; # One port was not free
    }
unknown's avatar
unknown committed
2290 2291
  }

unknown's avatar
unknown committed
2292
  return 0; # All ports free
unknown's avatar
unknown committed
2293 2294 2295
}


unknown's avatar
unknown committed
2296
sub initialize_servers {
2297

unknown's avatar
unknown committed
2298
  if ( using_extern() )
2299 2300 2301 2302 2303 2304 2305 2306 2307
  {
    # Running against an already started server, if the specified
    # vardir does not already exist it should be created
    if ( ! -d $opt_vardir )
    {
      setup_vardir();
    }
    else
    {
2308
      mtr_verbose("No need to create '$opt_vardir' it already exists");
2309 2310 2311
    }
  }
  else
2312
  {
unknown's avatar
unknown committed
2313 2314 2315 2316 2317 2318 2319 2320
    # Kill leftovers from previous run
    # using any pidfiles found in var/run
    kill_leftovers("$opt_vardir/run");

    if (check_ports_free()){
      # Some port was not free(which one has already been printed)
      mtr_error("Some port(s) was not free")
    }
unknown's avatar
unknown committed
2321

2322
    if ( ! $opt_start_dirty )
2323
    {
2324 2325 2326
      remove_stale_vardir();
      setup_vardir();

2327
      mysql_install_db(0);
2328
    }
2329
  }
2330
  check_running_as_root();
unknown's avatar
unknown committed
2331 2332 2333
}


unknown's avatar
unknown committed
2334
#
2335
# Remove all newline characters expect after semicolon
unknown's avatar
unknown committed
2336
#
2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
sub sql_to_bootstrap {
  my ($sql) = @_;
  my @lines= split(/\n/, $sql);
  my $result= "\n";
  my $delimiter= ';';

  foreach my $line (@lines) {

    # Change current delimiter if line starts with "delimiter"
    if ( $line =~ /^delimiter (.*)/ ) {
      my $new= $1;
      # Remove old delimiter from end of new
      $new=~ s/\Q$delimiter\E$//;
      $delimiter = $new;
      mtr_debug("changed delimiter to $delimiter");
      # No need to add the delimiter to result
      next;
    }
2355

2356 2357 2358 2359 2360 2361 2362 2363
    # Add newline if line ends with $delimiter
    # and convert the current delimiter to semicolon
    if ( $line =~ /\Q$delimiter\E$/ ){
      $line =~ s/\Q$delimiter\E$/;/;
      $result.= "$line\n";
      mtr_debug("Added default delimiter");
      next;
    }
2364

2365 2366 2367 2368 2369 2370
    # Remove comments starting with --
    if ( $line =~ /^\s*--/ ) {
      mtr_debug("Discarded $line");
      next;
    }

2371 2372 2373
    # Replace @HOSTNAME with localhost
    $line=~ s/\'\@HOSTNAME\@\'/localhost/;

2374 2375 2376 2377 2378 2379
    # Default, just add the line without newline
    # but with a space as separator
    $result.= "$line ";

  }
  return $result;
2380 2381 2382
}


unknown's avatar
unknown committed
2383
sub mysql_install_db {
2384
  my ($thread_num)= @_;
unknown's avatar
unknown committed
2385
  my $data_dir= "$opt_vardir/install.db";
unknown's avatar
unknown committed
2386

unknown's avatar
unknown committed
2387
  mtr_report("Installing system database...");
unknown's avatar
unknown committed
2388

2389
  my $args;
unknown's avatar
unknown committed
2390 2391 2392
  mtr_init_args(\$args);
  mtr_add_arg($args, "--no-defaults");
  mtr_add_arg($args, "--bootstrap");
unknown's avatar
unknown committed
2393
  mtr_add_arg($args, "--basedir=%s", $basedir);
unknown's avatar
unknown committed
2394
  mtr_add_arg($args, "--datadir=%s", $data_dir);
unknown's avatar
unknown committed
2395 2396
  mtr_add_arg($args, "--loose-skip-innodb");
  mtr_add_arg($args, "--loose-skip-ndbcluster");
2397
  mtr_add_arg($args, "--tmpdir=%s", "$opt_vardir/tmp/");
2398
  mtr_add_arg($args, "--core-file");
unknown's avatar
unknown committed
2399

2400 2401
  if ( $opt_debug )
  {
unknown's avatar
unknown committed
2402 2403
    mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap.trace",
		$path_vardir_trace);
2404 2405
  }

unknown's avatar
unknown committed
2406 2407
  mtr_add_arg($args, "--language=%s", $path_language);
  mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
unknown's avatar
unknown committed
2408

2409 2410 2411 2412 2413
  # If DISABLE_GRANT_OPTIONS is defined when the server is compiled (e.g.,
  # configure --disable-grant-options), mysqld will not recognize the
  # --bootstrap or --skip-grant-tables options.  The user can set
  # MYSQLD_BOOTSTRAP to the full path to a mysqld which does accept
  # --bootstrap, to accommodate this.
2414
  my $exe_mysqld_bootstrap = $ENV{'MYSQLD_BOOTSTRAP'} || find_mysqld($basedir);
2415

2416 2417 2418 2419 2420
  # ----------------------------------------------------------------------
  # export MYSQLD_BOOTSTRAP_CMD variable containing <path>/mysqld <args>
  # ----------------------------------------------------------------------
  $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args);

2421 2422
  return if $thread_num > 0; # Only generate MYSQLD_BOOTSTRAP_CMD in workers

2423 2424 2425
  # ----------------------------------------------------------------------
  # Create the bootstrap.sql file
  # ----------------------------------------------------------------------
2426
  my $bootstrap_sql_file= "$opt_vardir/tmp/bootstrap.sql";
2427

2428 2429 2430 2431
  if (-f "$path_sql_dir/mysql_system_tables.sql")
  {
    # Use the mysql database for system tables
    mtr_tofile($bootstrap_sql_file, "use mysql\n");
2432

2433 2434 2435 2436
    # Add the offical mysql system tables
    # for a production system
    mtr_appendfile_to_file("$path_sql_dir/mysql_system_tables.sql",
			   $bootstrap_sql_file);
2437

2438 2439 2440 2441
    # Add the mysql system tables initial data
    # for a production system
    mtr_appendfile_to_file("$path_sql_dir/mysql_system_tables_data.sql",
			   $bootstrap_sql_file);
2442

2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461
    # Add test data for timezone - this is just a subset, on a real
    # system these tables will be populated either by mysql_tzinfo_to_sql
    # or by downloading the timezone table package from our website
    mtr_appendfile_to_file("$path_sql_dir/mysql_test_data_timezone.sql",
			   $bootstrap_sql_file);

  }
  else
  {
    # Install db from init_db.sql that exist in early 5.1 and 5.0
    # versions of MySQL
    my $init_file= "$basedir/mysql-test/lib/init_db.sql";
    mtr_report(" - from '$init_file'");
    my $text= mtr_grab_file($init_file) or
      mtr_error("Can't open '$init_file': $!");

    mtr_tofile($bootstrap_sql_file,
	       sql_to_bootstrap($text));
  }
2462 2463 2464 2465 2466 2467 2468

  # Fill help tables, just an empty file when running from bk repo
  # but will be replaced by a real fill_help_tables.sql when
  # building the source dist
  mtr_appendfile_to_file("$path_sql_dir/fill_help_tables.sql",
			 $bootstrap_sql_file);

2469
  # Remove anonymous users
2470
  mtr_tofile($bootstrap_sql_file,
unknown's avatar
unknown committed
2471 2472 2473 2474 2475
	     "DELETE FROM mysql.user where user= '';\n");

  # Create mtr database
  mtr_tofile($bootstrap_sql_file,
	     "CREATE DATABASE mtr;\n");
2476

2477 2478 2479 2480
  # Add help tables and data for warning detection and supression
  mtr_tofile($bootstrap_sql_file,
             sql_to_bootstrap(mtr_grab_file("include/mtr_warnings.sql")));

2481 2482 2483 2484
  # Add procedures for checking server is restored after testcase
  mtr_tofile($bootstrap_sql_file,
             sql_to_bootstrap(mtr_grab_file("include/mtr_check.sql")));

2485 2486 2487
  # Log bootstrap command
  my $path_bootstrap_log= "$opt_vardir/log/bootstrap.log";
  mtr_tofile($path_bootstrap_log,
2488
	     "$exe_mysqld_bootstrap " . join(" ", @$args) . "\n");
2489

unknown's avatar
unknown committed
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502
  # Create directories mysql and test
  mkpath("$data_dir/mysql");
  mkpath("$data_dir/test");

  if ( My::SafeProcess->run
       (
	name          => "bootstrap",
	path          => $exe_mysqld_bootstrap,
	args          => \$args,
	input         => $bootstrap_sql_file,
	output        => $path_bootstrap_log,
	error         => $path_bootstrap_log,
	append        => 1,
2503
	verbose       => $opt_verbose,
unknown's avatar
unknown committed
2504
       ) != 0)
unknown's avatar
unknown committed
2505
  {
unknown's avatar
unknown committed
2506
    mtr_error("Error executing mysqld --bootstrap\n" .
2507 2508
              "Could not install system database from $bootstrap_sql_file\n" .
	      "see $path_bootstrap_log for errors");
unknown's avatar
unknown committed
2509 2510 2511 2512
  }
}


2513 2514 2515
sub run_testcase_check_skip_test($)
{
  my ($tinfo)= @_;
2516

unknown's avatar
unknown committed
2517 2518 2519 2520 2521 2522 2523 2524 2525 2526
  # ----------------------------------------------------------------------
  # If marked to skip, just print out and return.
  # Note that a test case not marked as 'skip' can still be
  # skipped later, because of the test case itself in cooperation
  # with the mysqltest program tells us so.
  # ----------------------------------------------------------------------

  if ( $tinfo->{'skip'} )
  {
    mtr_report_test_skipped($tinfo);
2527
    return 1;
unknown's avatar
unknown committed
2528 2529
  }

unknown's avatar
unknown committed
2530 2531 2532
  return 0;
}

2533

2534 2535
sub run_query {
  my ($tinfo, $mysqld, $query)= @_;
2536 2537 2538 2539 2540

  my $args;
  mtr_init_args(\$args);
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));
2541 2542 2543

  mtr_add_arg($args, "-e %s", $query);

2544 2545
  my $res= My::SafeProcess->run
    (
2546
     name          => "run_query -> ".$mysqld->name(),
2547 2548
     path          => $exe_mysql,
     args          => \$args,
2549 2550
     output        => '/dev/null',
     error         => '/dev/null'
unknown's avatar
unknown committed
2551 2552
    );

2553
  return $res
2554
}
unknown's avatar
unknown committed
2555

2556

2557 2558 2559 2560
sub do_before_run_mysqltest($)
{
  my $tinfo= shift;

2561
  # Remove old files produced by mysqltest
2562 2563 2564 2565 2566 2567
  my $base_file= mtr_match_extension($tinfo->{'result_file'},
				    "result"); # Trim extension
  unlink("$base_file.reject");
  unlink("$base_file.progress");
  unlink("$base_file.log");
  unlink("$base_file.warnings");
2568

unknown's avatar
unknown committed
2569 2570 2571 2572 2573 2574 2575 2576
  if ( $mysql_version_id < 50000 ) {
    # Set environment variable NDB_STATUS_OK to 1
    # if script decided to run mysqltest cluster _is_ installed ok
    $ENV{'NDB_STATUS_OK'} = "1";
  } elsif ( $mysql_version_id < 50100 ) {
    # Set environment variable NDB_STATUS_OK to YES
    # if script decided to run mysqltest cluster _is_ installed ok
    $ENV{'NDB_STATUS_OK'} = "YES";
2577
  }
2578
}
unknown's avatar
unknown committed
2579

2580

2581 2582 2583 2584 2585 2586 2587 2588
#
# Check all server for sideffects
#
# RETURN VALUE
#  0 ok
#  1 Check failed
#  >1 Fatal errro

2589
sub check_testcase($$)
2590
{
unknown's avatar
unknown committed
2591
  my ($tinfo, $mode)= @_;
2592
  my $tname= $tinfo->{name};
2593

2594 2595 2596
  # Start the mysqltest processes in parallel to save time
  # also makes it possible to wait for any process to exit during the check
  my %started;
unknown's avatar
unknown committed
2597
  foreach my $mysqld ( mysqlds() )
2598
  {
unknown's avatar
unknown committed
2599 2600
    if ( defined $mysqld->{'proc'} )
    {
2601 2602 2603 2604 2605
      my $proc= start_check_testcase($tinfo, $mode, $mysqld);
      $started{$proc->pid()}= $proc;
    }
  }

2606 2607 2608
  # Return immediately if no check proceess was started
  return 0 unless ( keys %started );

2609 2610 2611 2612 2613 2614
  while (1){
    my $result;
    my $proc= My::SafeProcess->wait_any();
    mtr_report("Got $proc");

    if ( delete $started{$proc->pid()} ) {
2615 2616 2617 2618

      my $err_file= $proc->user_data();
      my $base_file= mtr_match_extension($err_file, "err"); # Trim extension

2619 2620 2621 2622 2623 2624
      # One check testcase process returned
      my $res= $proc->exit_status();

      if ( $res == 0){
	# Check completed without problem

2625 2626 2627
	# Remove the .err file the check generated
	unlink($err_file);

2628 2629 2630 2631 2632
	# Remove the .result file the check generated
	if ( $mode eq 'after' ){
	  unlink("$base_file.result");
	}

2633 2634 2635 2636 2637 2638 2639 2640
	if ( keys(%started) == 0){
	  # All checks completed
	  return 0;
	}
	# Wait for next process to exit
	next;
      }
      else
unknown's avatar
unknown committed
2641
      {
2642 2643 2644
	if ( $mode eq "after" and $res == 1 )
	{
	  # Test failed, grab the report mysqltest has created
2645
	  my $report= mtr_grab_file($err_file);
2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656
	  $tinfo->{check}.=
	    "\nThe check of testcase '$tname' failed, this is the\n".
	      "diff between before and after:\n";
	  $tinfo->{check}.= $report;

	  # Check failed, mark the test case with that info
	  $tinfo->{'check_testcase_failed'}= 1;
	  $result= 1;
	}
	elsif ( $res )
	{
2657
	  my $report= mtr_grab_file($err_file);
2658 2659 2660 2661 2662 2663 2664
	  $tinfo->{comment}.=
	    "Could not execute 'check-testcase' $mode testcase '$tname':\n";
	  $tinfo->{comment}.= $report;

	  $result= 2;
	}

2665 2666 2667
	# Remove the .err file the check generated
	unlink($err_file);

2668 2669 2670
	# Remove the .result file the check generated
	unlink("$base_file.result");

unknown's avatar
unknown committed
2671 2672
      }
    }
2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
    else {
      # Unknown process returned, most likley a crash, abort everything
      $tinfo->{comment}=
	"Unexpected process $proc returned during ".
	"check testcase $mode test";
      $result= 3;
    }

    # Kill any check processes still running
    map($_->kill(), values(%started));

    return $result;
2685
  }
unknown's avatar
unknown committed
2686
}
2687

2688

unknown's avatar
unknown committed
2689 2690 2691 2692
sub mark_log {
  my ($log, $tinfo)= @_;
  my $log_msg= "CURRENT_TEST: $tinfo->{name}\n";
  mtr_tofile($log, $log_msg);
2693 2694
}

unknown's avatar
unknown committed
2695

2696 2697 2698 2699
sub find_testcase_skipped_reason($)
{
  my ($tinfo)= @_;

2700 2701 2702
  # Set default message
  $tinfo->{'comment'}= "Detected by testcase(no log file)";

2703 2704
  # Open the test log file
  my $F= IO::File->new($path_current_testlog)
2705
    or return;
2706 2707 2708 2709
  my $reason;

  while ( my $line= <$F> )
  {
unknown's avatar
unknown committed
2710
    # Look for "reason: <reason for skipping test>"
2711
    if ( $line =~ /reason: (.*)/ )
unknown's avatar
unknown committed
2712
    {
2713 2714 2715
      $reason= $1;
    }
  }
2716

2717 2718
  if ( ! $reason )
  {
2719
    mtr_warning("Could not find reason for skipping test in $path_current_testlog");
2720
    $reason= "Detected by testcase(reason unknown) ";
2721
  }
2722 2723 2724 2725
  $tinfo->{'comment'}= $reason;
}


unknown's avatar
unknown committed
2726 2727 2728 2729 2730
# Return timezone value of tinfo or default value
sub timezone {
  my ($tinfo)= @_;
  return $tinfo->{timezone} || "GMT-3";
}
2731 2732


unknown's avatar
unknown committed
2733 2734
# Storage for changed environment variables
my %old_env;
2735

unknown's avatar
unknown committed
2736 2737 2738
#
# Run a single test case
#
unknown's avatar
unknown committed
2739 2740 2741 2742 2743
# RETURN VALUE
#  0 OK
#  > 0 failure
#

2744 2745 2746
sub run_testcase ($) {
  my $tinfo=  shift;

unknown's avatar
unknown committed
2747 2748
  mtr_verbose("Running test:", $tinfo->{name});

2749 2750 2751
  # -------------------------------------------------------
  # Init variables that can change between each test case
  # -------------------------------------------------------
unknown's avatar
unknown committed
2752 2753 2754
  my $timezone= timezone($tinfo);
  $ENV{'TZ'}= $timezone;
  mtr_verbose("Setting timezone: $timezone");
2755

unknown's avatar
unknown committed
2756
  if ( ! using_extern() )
2757
  {
unknown's avatar
unknown committed
2758 2759 2760
    my @restart= servers_need_restart($tinfo);
    if ( @restart != 0) {
      stop_servers($tinfo, @restart );
2761
    }
unknown's avatar
unknown committed
2762

unknown's avatar
unknown committed
2763 2764
    if ( started(all_servers()) == 0 )
    {
2765 2766 2767 2768

      # Remove old datadirs
      clean_datadir();

unknown's avatar
unknown committed
2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794
      # Restore old ENV
      while (my ($option, $value)= each( %old_env )) {
	if (defined $value){
	  mtr_verbose("Restoring $option to $value");
	  $ENV{$option}= $value;
	} else {
	  mtr_verbose("Removing $option");
	  delete($ENV{$option});
	}
      }
      %old_env= ();

      mtr_verbose("Generating my.cnf from '$tinfo->{template_path}'");

      # Generate new config file from template
      $config= My::ConfigFactory->new_config
	( {
	   basedir         => $basedir,
	   template_path   => $tinfo->{template_path},
	   extra_template_path => $tinfo->{extra_template_path},
	   vardir          => $opt_vardir,
	   tmpdir          => $opt_tmpdir,
	   baseport        => $opt_baseport,
	   #hosts          => [ 'host1', 'host2' ],
	   user            => $opt_user,
	   password        => '',
2795
	   ssl             => $opt_ssl_supported,
unknown's avatar
unknown committed
2796
	   embedded        => $opt_embedded_server,
unknown's avatar
unknown committed
2797 2798
	  }
	);
2799

unknown's avatar
unknown committed
2800 2801
      # Write the new my.cnf
      $config->save($path_config_file);
2802

unknown's avatar
unknown committed
2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820
      # Remember current config so a restart can occur when a test need
      # to use a different one
      $current_config_name= $tinfo->{template_path};

      #
      # Set variables in the ENV section
      #
      foreach my $option ($config->options_in_group("ENV"))
      {
	# Save old value to restore it before next time
	$old_env{$option->name()}= $ENV{$option->name()};

	mtr_verbose($option->name(), "=",$option->value());
	$ENV{$option->name()}= $option->value();
      }
    }

    # Write start of testcase to log
2821
    mark_log($path_current_testlog, $tinfo);
unknown's avatar
unknown committed
2822 2823

    if (start_servers($tinfo))
unknown's avatar
unknown committed
2824
    {
2825 2826
      report_failure_and_restart($tinfo);
      return 1;
unknown's avatar
unknown committed
2827
    }
2828
  }
unknown's avatar
unknown committed
2829

unknown's avatar
unknown committed
2830 2831
  # --------------------------------------------------------------------
  # If --start or --start-dirty given, stop here to let user manually
2832
  # run tests
unknown's avatar
unknown committed
2833
  # ----------------------------------------------------------------------
unknown's avatar
unknown committed
2834
  if ( $opt_start or $opt_start_dirty )
unknown's avatar
unknown committed
2835
  {
unknown's avatar
unknown committed
2836 2837
    mtr_print("\nStarted", started(all_servers()));
    mtr_print("Waiting for server(s) to exit...");
2838 2839 2840
    my $proc= My::SafeProcess->wait_any();
    if ( grep($proc eq $_, started(all_servers())) )
    {
unknown's avatar
unknown committed
2841
      mtr_print("Server $proc died");
2842 2843
      exit(1);
    }
unknown's avatar
unknown committed
2844
    mtr_print("Unknown process $proc died");
2845
    exit(1);
unknown's avatar
unknown committed
2846 2847
  }

unknown's avatar
unknown committed
2848 2849 2850 2851
  my $test_timeout_proc= My::SafeProcess->timer($opt_testcase_timeout * 60);

  do_before_run_mysqltest($tinfo);

2852 2853 2854
  if ( $opt_check_testcases and check_testcase($tinfo, "before") ){
    # Failed to record state of server or server crashed
    report_failure_and_restart($tinfo);
2855 2856 2857 2858

    # Stop the test case timer
    $test_timeout_proc->kill();

2859
    return 1;
unknown's avatar
unknown committed
2860
  }
2861

unknown's avatar
unknown committed
2862
  my $test= start_mysqltest($tinfo);
2863

unknown's avatar
unknown committed
2864 2865 2866 2867
  while (1)
  {
    my $proc= My::SafeProcess->wait_any();
    unless ( defined $proc )
unknown's avatar
unknown committed
2868
    {
unknown's avatar
unknown committed
2869
      mtr_error("wait_any failed");
unknown's avatar
unknown committed
2870
    }
unknown's avatar
unknown committed
2871 2872 2873 2874 2875 2876
    mtr_verbose("Got $proc");

    # ----------------------------------------------------
    # Was it the test program that exited
    # ----------------------------------------------------
    if ($proc eq $test)
unknown's avatar
unknown committed
2877
    {
2878 2879 2880
      # Stop the test case timer
      $test_timeout_proc->kill();

unknown's avatar
unknown committed
2881 2882 2883 2884
      my $res= $test->exit_status();

      if ( $res == 0 )
      {
2885 2886 2887 2888 2889 2890 2891 2892
	if ( $opt_warnings and check_warnings($tinfo) )
	{
	  # Found unexpected warnings
	  report_failure_and_restart($tinfo);
	  $res= 1;
	}
	else
	{
unknown's avatar
unknown committed
2893
	  mtr_report_test_passed($tinfo);
2894
	}
unknown's avatar
unknown committed
2895

2896 2897 2898
	my $check_res;
	if ( $opt_check_testcases and
	     $check_res= check_testcase($tinfo, "after"))
unknown's avatar
unknown committed
2899
	{
2900 2901 2902 2903 2904 2905 2906 2907 2908 2909
	  if ($check_res == 1) {
	    # Test case had sideeffects, not fatal error, just continue
	    stop_all_servers();
	    mtr_report("Resuming tests...\n");
	  }
	  else {
	    # Test case check failed fatally, probably a server crashed
	    report_failure_and_restart($tinfo);
	    return 1;
	  }
unknown's avatar
unknown committed
2910 2911 2912 2913 2914 2915
	}
      }
      elsif ( $res == 62 )
      {
	# Testcase itself tell us to skip this one
	$tinfo->{skip_detected_by_test}= 1;
2916
	# Try to get reason from test log file
unknown's avatar
unknown committed
2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940
	find_testcase_skipped_reason($tinfo);
	mtr_report_test_skipped($tinfo);
      }
      elsif ( $res == 65 )
      {
	# Testprogram killed by signal
	$tinfo->{comment}=
	  "testprogram crashed(returned code $res)";
	report_failure_and_restart($tinfo);
      }
      elsif ( $res == 1 )
      {
	# Test case failure reported by mysqltest
	report_failure_and_restart($tinfo);
      }
      else
      {
	# mysqltest failed, probably crashed
	$tinfo->{comment}=
	  "mysqltest failed with unexpected return code $res";
	report_failure_and_restart($tinfo);
      }

      # Save info from this testcase run to mysqltest.log
2941 2942 2943 2944 2945
      if( -f $path_current_testlog)
      {
	mtr_appendfile_to_file($path_current_testlog, $path_testlog);
	unlink($path_current_testlog);
      }
unknown's avatar
unknown committed
2946

unknown's avatar
unknown committed
2947
      return ($res == 62) ? 0 : $res;
2948

unknown's avatar
unknown committed
2949
    }
unknown's avatar
unknown committed
2950 2951 2952 2953 2954

    # ----------------------------------------------------
    # Check if it was an expected crash
    # ----------------------------------------------------
    if ( check_expected_crash_and_restart($proc) )
2955
    {
unknown's avatar
unknown committed
2956
      next;
2957
    }
unknown's avatar
unknown committed
2958

2959 2960 2961 2962 2963
    # ----------------------------------------------------
    # Stop the test case timer
    # ----------------------------------------------------
    $test_timeout_proc->kill();

unknown's avatar
unknown committed
2964 2965 2966 2967 2968 2969 2970 2971 2972
    # ----------------------------------------------------
    # It's not mysqltest that has exited, kill it
    # ----------------------------------------------------
    $test->kill();

    # ----------------------------------------------------
    # Check if it was a server that died
    # ----------------------------------------------------
    if ( grep($proc eq $_, started(all_servers())) )
unknown's avatar
unknown committed
2973
    {
unknown's avatar
unknown committed
2974 2975
      # Server failed, probably crashed
      $tinfo->{comment}=
2976
	"Server $proc failed during test run";
unknown's avatar
unknown committed
2977

unknown's avatar
unknown committed
2978
      report_failure_and_restart($tinfo);
unknown's avatar
unknown committed
2979
      return 1;
unknown's avatar
unknown committed
2980
    }
unknown's avatar
unknown committed
2981 2982 2983 2984 2985

    # ----------------------------------------------------
    # Check if testcase timer expired
    # ----------------------------------------------------
    if ( $proc eq $test_timeout_proc )
unknown's avatar
unknown committed
2986
    {
unknown's avatar
unknown committed
2987 2988
      mtr_report("Test case timeout!");
      $tinfo->{'timeout'}= 1;           # Mark as timeout
unknown's avatar
unknown committed
2989
      report_failure_and_restart($tinfo);
unknown's avatar
unknown committed
2990
      return 1;
unknown's avatar
unknown committed
2991
    }
2992

unknown's avatar
unknown committed
2993
    mtr_error("Unhandled process $proc exited");
2994
  }
unknown's avatar
unknown committed
2995
  mtr_error("Should never come here");
unknown's avatar
unknown committed
2996
}
unknown's avatar
unknown committed
2997

2998

2999 3000 3001 3002 3003 3004
# Run include/check-warnings.test
#
# RETURN VALUE
#  0 OK
#  1 Check failed
#
3005
sub start_check_warnings ($$) {
3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022
  my $tinfo=    shift;
  my $mysqld=   shift;

  my $name= "warnings-".$mysqld->name();
  my $tname= $tinfo->{name};

  my $args;
  mtr_init_args(\$args);

  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));

  mtr_add_arg($args, "--silent");
  mtr_add_arg($args, "--skip-safemalloc");
  mtr_add_arg($args, "--test-file=%s", "include/check-warnings.test");

  my $errfile= "$opt_vardir/tmp/$name.err";
3023
  my $proc= My::SafeProcess->new
3024 3025 3026 3027 3028 3029
    (
     name          => $name,
     path          => $exe_mysqltest,
     error         => $errfile,
     output        => $errfile,
     args          => \$args,
3030
     user_data     => $errfile,
3031
    );
3032 3033
  mtr_verbose("Started $proc");
  return $proc;
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044
}


#
# Loop through our list of processes and check the error log
# for unexepcted errors and warnings
#
sub check_warnings ($) {
  my ($tinfo)= @_;
  my $res= 0;

3045 3046
  my $tname= $tinfo->{name};

3047
  # Clear previous warnings
3048
  delete($tinfo->{warnings});
3049

3050 3051 3052
  # Start the mysqltest processes in parallel to save time
  # also makes it possible to wait for any process to exit during the check
  my %started;
3053 3054
  foreach my $mysqld ( mysqlds() )
  {
3055 3056 3057 3058 3059 3060 3061
    if ( defined $mysqld->{'proc'} )
    {
      my $proc= start_check_warnings($tinfo, $mysqld);
      $started{$proc->pid()}= $proc;
    }
  }

3062 3063 3064
  # Return immediately if no check proceess was started
  return 0 unless ( keys %started );

3065 3066 3067 3068 3069 3070 3071 3072
  while (1){
    my $result= 0;
    my $proc= My::SafeProcess->wait_any();
    mtr_report("Got $proc");

    if ( delete $started{$proc->pid()} ) {
      # One check warning process returned
      my $res= $proc->exit_status();
3073
      my $err_file= $proc->user_data();
3074 3075 3076 3077 3078

      if ( $res == 0 or $res == 62 ){

	if ( $res == 0 ) {
	  # Check completed with problem
3079
	  my $report= mtr_grab_file($err_file);
3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091
	  # Log to var/log/warnings file
	  mtr_tofile("$opt_vardir/log/warnings",
		     $tname."\n".$report);

	  $tinfo->{'warnings'}.= $report;
	  $result= 1;
	}

	if ( $res == 62 ) {
	  # Test case was ok and called "skip"
	  ;
	}
3092 3093
	# Remove the .err file the check generated
	unlink($err_file);
3094 3095 3096 3097 3098 3099 3100 3101 3102 3103

	if ( keys(%started) == 0){
	  # All checks completed
	  return $result;
	}
	# Wait for next process to exit
	next;
      }
      else
      {
3104
	my $report= mtr_grab_file($err_file);
3105 3106 3107 3108 3109 3110
	$tinfo->{comment}.=
	  "Could not execute 'check-warnings' for testcase '$tname':";
	$tinfo->{comment}.= $report;

	$result= 2;
      }
3111 3112
      # Remove the .err file the check generated
      unlink($err_file);
3113 3114 3115 3116 3117 3118 3119
    }
    else {
      # Unknown process returned, most likley a crash, abort everything
      $tinfo->{comment}=
	"Unexpected process $proc returned during ".
	"check warnings";
      $result= 3;
3120
    }
3121 3122 3123 3124 3125

    # Kill any check processes still running
    map($_->kill(), values(%started));

    return $result;
3126
  }
3127 3128 3129 3130 3131 3132




  return $res;

3133 3134 3135 3136
  return $res;
}


3137
#
unknown's avatar
unknown committed
3138 3139 3140
# Loop through our list of processes and look for and entry
# with the provided pid, if found check for the file indicating
# expected crash and restart it.
3141
#
unknown's avatar
unknown committed
3142 3143
sub check_expected_crash_and_restart {
  my ($proc)= @_;
3144

unknown's avatar
unknown committed
3145
  foreach my $mysqld ( mysqlds() )
3146
  {
unknown's avatar
unknown committed
3147 3148 3149 3150 3151 3152 3153
    next unless ( $mysqld->{proc} eq $proc );

    # Check if crash expected by looking at the .expect file
    # in var/tmp
    my $expect_file= "$opt_vardir/tmp/".$mysqld->name().".expect";
    if ( -f $expect_file )
    {
3154
      mtr_report("Crash was expected, file '$expect_file' exists");
unknown's avatar
unknown committed
3155 3156 3157 3158 3159 3160
      # Start server with same settings as last time
      mysqld_start($mysqld, $mysqld->{'started_opts'});
      unlink($expect_file);
    }

    return 1;
3161
  }
unknown's avatar
unknown committed
3162 3163 3164

  # Not an expected crash
  return 0;
3165 3166
}

3167

3168 3169 3170
# Remove all files and subdirectories of a directory
sub clean_dir {
  my ($dir)= @_;
unknown's avatar
unknown committed
3171
  mtr_verbose("clean_dir: $dir");
3172 3173 3174 3175 3176 3177 3178 3179 3180
  finddepth(
	  { no_chdir => 1,
	    wanted => sub {
	      if (-d $_){
		# A dir
		if ($_ eq $dir){
		  # The dir to clean
		  return;
		} else {
unknown's avatar
unknown committed
3181
		  mtr_verbose("rmdir: '$_'");
unknown's avatar
unknown committed
3182
		  rmdir($_) or mtr_warning("rmdir($_) failed: $!");
3183 3184 3185
		}
	      } else {
		# Hopefully a file
unknown's avatar
unknown committed
3186
		mtr_verbose("unlink: '$_'");
unknown's avatar
unknown committed
3187
		unlink($_) or mtr_warning("unlink($_) failed: $!");
3188 3189 3190 3191 3192 3193 3194
	      }
	    }
	  },
	    $dir);
}


3195 3196 3197 3198
sub clean_datadir {

  mtr_verbose("Cleaning datadirs...");

unknown's avatar
unknown committed
3199 3200 3201 3202
  if (started(all_servers()) != 0){
    mtr_error("Trying to clean datadir before all servers stopped");
  }

3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220
  foreach my $cluster ( clusters() )
  {
    my $cluster_dir= "$opt_vardir/".$cluster->{name};
    mtr_verbose(" - removing '$cluster_dir'");
    rmtree($cluster_dir);

  }

  foreach my $mysqld ( mysqlds() )
  {
    my $mysqld_dir= dirname($mysqld->value('datadir'));
    if (-d $mysqld_dir ) {
      mtr_verbose(" - removing '$mysqld_dir'");
      rmtree($mysqld_dir);
    }
  }

  # Remove all files in tmp and var/tmp
3221
  clean_dir("$opt_vardir/tmp");
3222
  if ($opt_tmpdir ne "$opt_vardir/tmp"){
3223
    clean_dir($opt_tmpdir);
3224 3225 3226 3227 3228 3229 3230 3231 3232
  }
}


#
# Save datadir before it's removed
#
sub save_datadir_after_failure($$) {
  my ($dir, $savedir)= @_;
unknown's avatar
unknown committed
3233

3234 3235 3236
  mtr_report(" - saving '$dir'");
  my $dir_name= basename($dir);
  rename("$dir", "$savedir/$dir_name");
3237
}
3238

3239 3240 3241 3242 3243 3244 3245 3246 3247

sub after_failure ($) {
  my ($tinfo)= @_;

  mtr_report("Saving datadirs...");

  my $save_dir= "$opt_vardir/log/";
  $save_dir.= $tinfo->{name};
  # Add combination name if any
unknown's avatar
unknown committed
3248
  $save_dir.= "-$tinfo->{combination}"
3249 3250
    if defined $tinfo->{combination};

3251 3252 3253
  # Save savedir  path for server
  $tinfo->{savedir}= $save_dir;

3254 3255 3256 3257 3258
  mkpath($save_dir) if ! -d $save_dir;

  # Save the used my.cnf file
  copy($path_config_file, $save_dir);

3259 3260 3261
  # Copy the tmp dir
  copytree("$opt_vardir/tmp/", "$save_dir/tmp/");

3262 3263 3264 3265
  if ( clusters() ) {
    foreach my $cluster ( clusters() ) {
      my $cluster_dir= "$opt_vardir/".$cluster->{name};
      save_datadir_after_failure($cluster_dir, $save_dir);
3266 3267
    }
  }
3268 3269 3270 3271 3272
  else {
    foreach my $mysqld ( mysqlds() ) {
      my $data_dir= $mysqld->value('datadir');
      save_datadir_after_failure(dirname($data_dir), $save_dir);
    }
3273
  }
3274 3275
}

unknown's avatar
unknown committed
3276

unknown's avatar
unknown committed
3277 3278 3279
sub report_failure_and_restart ($) {
  my $tinfo= shift;

3280
  stop_all_servers();
3281

3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301
  $tinfo->{'result'}= 'MTR_RES_FAILED';

  my $test_failures= $tinfo->{'failures'} || 0;
  $tinfo->{'failures'}=  $test_failures + 1;


  my $logfile= $path_current_testlog;
  if ( $tinfo->{comment} )
  {
    # The test failure has been detected by mysql-test-run.pl
    # when starting the servers or due to other error, the reason for
    # failing the test is saved in "comment"
    ;
  }
  elsif ( defined $logfile and -f $logfile )
  {
    # Test failure was detected by test tool and its report
    # about what failed has been saved to file. Save the report
    # in tinfo
    $tinfo->{logfile}= mtr_fromfile($logfile);
unknown's avatar
unknown committed
3302
  }
3303

3304
  after_failure($tinfo);
3305

3306 3307
  mtr_report_test($tinfo);

unknown's avatar
unknown committed
3308 3309 3310
}


unknown's avatar
unknown committed
3311 3312
sub run_sh_script {
  my ($script)= @_;
unknown's avatar
unknown committed
3313

unknown's avatar
unknown committed
3314
  return 0 unless defined $script;
3315

unknown's avatar
unknown committed
3316 3317 3318
  mtr_verbose("Running '$script'");
  my $ret= system("/bin/sh $script") >> 8;
  return $ret;
unknown's avatar
unknown committed
3319 3320
}

unknown's avatar
unknown committed
3321

unknown's avatar
unknown committed
3322 3323
sub mysqld_stop {
  my $mysqld= shift or die "usage: mysqld_stop(<mysqld>)";
unknown's avatar
unknown committed
3324

unknown's avatar
unknown committed
3325 3326
  my $args;
  mtr_init_args(\$args);
3327

unknown's avatar
unknown committed
3328 3329 3330 3331 3332 3333 3334
  mtr_add_arg($args, "--no-defaults");
  mtr_add_arg($args, "--user=%s", $opt_user);
  mtr_add_arg($args, "--password=");
  mtr_add_arg($args, "--port=%d", $mysqld->value('port'));
  mtr_add_arg($args, "--host=%s", $mysqld->value('#host'));
  mtr_add_arg($args, "--connect_timeout=20");
  mtr_add_arg($args, "--protocol=tcp");
unknown's avatar
unknown committed
3335

unknown's avatar
unknown committed
3336
  mtr_add_arg($args, "shutdown");
3337

unknown's avatar
unknown committed
3338 3339 3340 3341 3342 3343
  My::SafeProcess->run
    (
     name          => "mysqladmin shutdown ".$mysqld->name(),
     path          => $exe_mysqladmin,
     args          => \$args,
     error         => "/dev/null",
unknown's avatar
unknown committed
3344

unknown's avatar
unknown committed
3345
    );
unknown's avatar
unknown committed
3346 3347
}

unknown's avatar
unknown committed
3348

unknown's avatar
unknown committed
3349
sub mysqld_arguments ($$$) {
unknown's avatar
unknown committed
3350
  my $args=              shift;
3351
  my $mysqld=            shift;
3352
  my $extra_opts=        shift;
unknown's avatar
unknown committed
3353

unknown's avatar
unknown committed
3354
  mtr_add_arg($args, "--defaults-file=%s",  $path_config_file);
3355

unknown's avatar
unknown committed
3356
  # When mysqld is run by a root user(euid is 0), it will fail
unknown's avatar
unknown committed
3357 3358
  # to start unless we specify what user to run as, see BUG#30630
  my $euid= $>;
unknown's avatar
unknown committed
3359
  if (!IS_WINDOWS and $euid == 0 and
3360
      (grep(/^--user/, @$extra_opts)) == 0) {
unknown's avatar
unknown committed
3361
    mtr_add_arg($args, "--user=root");
unknown's avatar
unknown committed
3362 3363
  }

unknown's avatar
unknown committed
3364
  if ( $opt_valgrind_mysqld )
unknown's avatar
unknown committed
3365
  {
unknown's avatar
unknown committed
3366
    mtr_add_arg($args, "--skip-safemalloc");
3367 3368 3369

    if ( $mysql_version_id < 50100 )
    {
unknown's avatar
unknown committed
3370
      mtr_add_arg($args, "--skip-bdb");
3371
    }
unknown's avatar
unknown committed
3372 3373
  }

3374 3375
  if ( $mysql_version_id >= 50106 )
  {
unknown's avatar
unknown committed
3376
    # Turn on logging to both tables and file
unknown's avatar
unknown committed
3377
    mtr_add_arg($args, "--log-output=table,file");
3378 3379
  }

3380
  # Check if "extra_opt" contains skip-log-bin
3381
  my $skip_binlog= grep(/^(--|--loose-)skip-log-bin/, @$extra_opts);
unknown's avatar
unknown committed
3382

unknown's avatar
unknown committed
3383
  # Indicate to mysqld it will be debugged in debugger
unknown's avatar
unknown committed
3384
  if ( $glob_debugger )
unknown's avatar
unknown committed
3385
  {
unknown's avatar
unknown committed
3386
    mtr_add_arg($args, "--gdb");
unknown's avatar
unknown committed
3387 3388
  }

unknown's avatar
unknown committed
3389
  my $found_skip_core= 0;
3390
  foreach my $arg ( @$extra_opts )
unknown's avatar
unknown committed
3391
  {
3392
    # Allow --skip-core-file to be set in <testname>-[master|slave].opt file
unknown's avatar
unknown committed
3393 3394 3395 3396
    if ($arg eq "--skip-core-file")
    {
      $found_skip_core= 1;
    }
3397 3398 3399 3400
    elsif ($skip_binlog and mtr_match_prefix($arg, "--binlog-format"))
    {
      ; # Dont add --binlog-format when running without binlog
    }
unknown's avatar
unknown committed
3401 3402
    else
    {
unknown's avatar
unknown committed
3403
      mtr_add_arg($args, "%s", $arg);
unknown's avatar
unknown committed
3404 3405 3406 3407
    }
  }
  if ( !$found_skip_core )
  {
unknown's avatar
unknown committed
3408
    mtr_add_arg($args, "%s", "--core-file");
unknown's avatar
unknown committed
3409 3410 3411 3412 3413 3414
  }

  return $args;
}


3415

unknown's avatar
unknown committed
3416
sub mysqld_start ($$) {
unknown's avatar
unknown committed
3417
  my $mysqld=            shift;
3418 3419 3420
  my $extra_opts=        shift;

  mtr_verbose(My::Options::toStr("mysqld_start", @$extra_opts));
unknown's avatar
unknown committed
3421

3422
  my $exe= find_mysqld($mysqld->value('basedir'));
unknown's avatar
unknown committed
3423 3424
  my $wait_for_pid_file= 1;

3425
  mtr_error("Internal error: mysqld should never be started for embedded")
unknown's avatar
unknown committed
3426
    if $opt_embedded_server;
unknown's avatar
unknown committed
3427

unknown's avatar
unknown committed
3428
  my $args;
unknown's avatar
unknown committed
3429 3430
  mtr_init_args(\$args);

unknown's avatar
unknown committed
3431
  if ( $opt_valgrind_mysqld )
unknown's avatar
unknown committed
3432
  {
unknown's avatar
unknown committed
3433
    valgrind_arguments($args, \$exe);
unknown's avatar
unknown committed
3434 3435
  }

unknown's avatar
unknown committed
3436
  mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));
3437
  mysqld_arguments($args,$mysqld,$extra_opts);
unknown's avatar
unknown committed
3438

unknown's avatar
unknown committed
3439 3440 3441 3442 3443 3444
  if ( $opt_debug )
  {
    mtr_add_arg($args, "--debug=d:t:i:A,%s/log/%s.trace",
		$path_vardir_trace, $mysqld->name());
  }

unknown's avatar
unknown committed
3445
  if ( $opt_gdb || $opt_manual_gdb )
unknown's avatar
unknown committed
3446
  {
unknown's avatar
unknown committed
3447
    gdb_arguments(\$args, \$exe, $mysqld->name());
unknown's avatar
unknown committed
3448 3449 3450
  }
  elsif ( $opt_ddd || $opt_manual_ddd )
  {
unknown's avatar
unknown committed
3451
    ddd_arguments(\$args, \$exe, $mysqld->name());
unknown's avatar
unknown committed
3452
  }
3453 3454
  elsif ( $opt_debugger )
  {
unknown's avatar
unknown committed
3455
    debugger_arguments(\$args, \$exe, $mysqld->name());
unknown's avatar
unknown committed
3456
  }
3457 3458
  elsif ( $opt_manual_debug )
  {
unknown's avatar
unknown committed
3459
     print "\nStart $mysqld->name() in your debugger\n" .
3460 3461 3462 3463 3464 3465 3466 3467
           "dir: $glob_mysql_test_dir\n" .
           "exe: $exe\n" .
	   "args:  " . join(" ", @$args)  . "\n\n" .
	   "Waiting ....\n";

     # Indicate the exe should not be started
    $exe= undef;
  }
unknown's avatar
unknown committed
3468 3469 3470 3471 3472
  else
  {
    # Default to not wait until pid file has been created
    $wait_for_pid_file= 0;
  }
unknown's avatar
unknown committed
3473

unknown's avatar
unknown committed
3474 3475
  # Remove the old pidfile if any
  unlink($mysqld->value('pid-file'));
3476

unknown's avatar
unknown committed
3477 3478
  my $output= $mysqld->value('log-error');
  if ( $opt_valgrind and $opt_debug )
unknown's avatar
unknown committed
3479
  {
unknown's avatar
unknown committed
3480 3481 3482 3483
    # When both --valgrind and --debug is selected, send
    # all output to the trace file, making it possible to
    # see the exact location where valgrind complains
    $output= "$opt_vardir/log/".$mysqld->name().".trace";
unknown's avatar
unknown committed
3484 3485
  }

unknown's avatar
unknown committed
3486
  if ( defined $exe )
unknown's avatar
unknown committed
3487
  {
unknown's avatar
unknown committed
3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500
    $mysqld->{'proc'}= My::SafeProcess->new
      (
       name          => $mysqld->name(),
       path          => $exe,
       args          => \$args,
       output        => $output,
       error         => $output,
       append        => 1,
       verbose       => $opt_verbose,
       host          => undef,
       shutdown      => sub { mysqld_stop($mysqld) },
      );
    mtr_verbose("Started $mysqld->{proc}");
unknown's avatar
unknown committed
3501 3502
  }

unknown's avatar
unknown committed
3503 3504 3505 3506 3507 3508 3509
  if ( $wait_for_pid_file &&
       !sleep_until_file_created($mysqld->value('pid-file'),
				 $opt_start_timeout,
				 $mysqld->{'proc'}))
  {
    mtr_error("Failed to start mysqld $mysqld->name()");
  }
3510 3511

  # Remember options used when starting
3512
  $mysqld->{'started_opts'}= $extra_opts;
3513

unknown's avatar
unknown committed
3514
  return;
unknown's avatar
unknown committed
3515 3516
}

unknown's avatar
unknown committed
3517

unknown's avatar
unknown committed
3518
sub stop_all_servers () {
unknown's avatar
unknown committed
3519

unknown's avatar
unknown committed
3520
  mtr_verbose("Stopping all servers...");
unknown's avatar
unknown committed
3521

unknown's avatar
unknown committed
3522 3523 3524
  # Kill all started servers
  My::SafeProcess::shutdown(0, # shutdown timeout 0 => kill
			    started(all_servers()));
unknown's avatar
unknown committed
3525

unknown's avatar
unknown committed
3526 3527 3528 3529 3530 3531 3532
  # Remove pidfiles
  foreach my $server ( all_servers() )
  {
    my $pid_file= $server->if_exist('pid-file');
    unlink($pid_file) if defined $pid_file;
  }

unknown's avatar
unknown committed
3533 3534
  # Mark servers as stopped
  map($_->{proc}= undef, all_servers());
unknown's avatar
unknown committed
3535

unknown's avatar
unknown committed
3536 3537
}

unknown's avatar
unknown committed
3538

unknown's avatar
unknown committed
3539 3540 3541
# Find out if server should be restarted for this test
sub server_need_restart {
  my ($tinfo, $server)= @_;
unknown's avatar
unknown committed
3542

unknown's avatar
unknown committed
3543
  if ( using_extern() )
unknown's avatar
unknown committed
3544
  {
unknown's avatar
unknown committed
3545
    mtr_verbose_restart($server, "no restart for --extern server");
unknown's avatar
unknown committed
3546
    return 0;
3547
  }
unknown's avatar
unknown committed
3548 3549

  if ( $opt_embedded_server )
3550
  {
unknown's avatar
unknown committed
3551
    mtr_verbose_restart($server, "no start or restart for embedded server");
unknown's avatar
unknown committed
3552
    return 0;
unknown's avatar
unknown committed
3553
  }
unknown's avatar
unknown committed
3554 3555

  if ( $tinfo->{'force_restart'} ) {
unknown's avatar
unknown committed
3556
    mtr_verbose_restart($server, "forced in .opt file");
unknown's avatar
unknown committed
3557
    return 1;
unknown's avatar
unknown committed
3558
  }
unknown's avatar
unknown committed
3559 3560

  if ( $tinfo->{template_path} ne $current_config_name)
3561
  {
unknown's avatar
unknown committed
3562
    mtr_verbose_restart($server, "using different config file");
unknown's avatar
unknown committed
3563
    return 1;
3564
  }
unknown's avatar
unknown committed
3565 3566

  if ( $tinfo->{'master_sh'}  || $tinfo->{'slave_sh'} )
unknown's avatar
unknown committed
3567
  {
unknown's avatar
unknown committed
3568
    mtr_verbose_restart($server, "sh script to run");
unknown's avatar
unknown committed
3569
    return 1;
unknown's avatar
unknown committed
3570
  }
unknown's avatar
unknown committed
3571 3572

  if ( ! started($server) )
3573
  {
unknown's avatar
unknown committed
3574
    mtr_verbose_restart($server, "not started");
unknown's avatar
unknown committed
3575
    return 1;
3576
  }
unknown's avatar
unknown committed
3577 3578 3579

  my $started_tinfo= $server->{'started_tinfo'};
  if ( defined $started_tinfo )
3580
  {
unknown's avatar
unknown committed
3581 3582 3583 3584

    # Check if timezone of  test that server was started
    # with differs from timezone of next test
    if ( timezone($started_tinfo) ne timezone($tinfo) )
3585
    {
unknown's avatar
unknown committed
3586
      mtr_verbose_restart($server, "different timezone");
unknown's avatar
unknown committed
3587
      return 1;
3588
    }
3589
  }
3590

3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601
  # Temporary re-enable the "always restart slave" hack
  # this should be removed asap, but will require that each rpl
  # testcase cleanup better after itself - ie. stop and reset
  # replication
  # Use the "#!use-slave-opt" marker to detect that this is a "slave"
  # server
  if ( $server->option("#!use-slave-opt") ){
    mtr_verbose_restart($server, "Always restart slave(s)");
    return 1;
  }

3602
  my $is_mysqld= grep ($server eq $_, mysqlds());
3603 3604
  if ($is_mysqld)
  {
unknown's avatar
unknown committed
3605

3606 3607
    # Check that running process was started with same options
    # as the current test requires
3608
    my $extra_opts= get_extra_opts($server, $tinfo);
3609
    my $started_opts= $server->{'started_opts'};
3610 3611

    if (!My::Options::same($started_opts, $extra_opts) )
3612
    {
3613
      my $use_dynamic_option_switch= 0;
unknown's avatar
unknown committed
3614 3615 3616 3617 3618 3619 3620
      if (!$use_dynamic_option_switch)
      {
	mtr_verbose_restart($server, "running with different options '" .
			    join(" ", @{$extra_opts}) . "' != '" .
			    join(" ", @{$started_opts}) . "'" );
	return 1;
      }
3621

3622 3623 3624 3625 3626 3627 3628 3629 3630 3631
      mtr_verbose(My::Options::toStr("started_opts", @$started_opts));
      mtr_verbose(My::Options::toStr("extra_opts", @$extra_opts));

      # Get diff and check if dynamic switch is possible
      my @diff_opts= My::Options::diff($started_opts, $extra_opts);
      mtr_verbose(My::Options::toStr("diff_opts", @diff_opts));

      my $query= My::Options::toSQL(@diff_opts);
      mtr_verbose("Attempting dynamic switch '$query'");
      if (run_query($tinfo, $server, $query)){
3632
	mtr_verbose("Restart: running with different options '" .
3633
		    join(" ", @{$extra_opts}) . "' != '" .
unknown's avatar
unknown committed
3634
		    join(" ", @{$started_opts}) . "'" );
3635 3636
	return 1;
      }
3637 3638 3639

      # Remember the dynamically set options
      $server->{'started_opts'}= $extra_opts;
3640
    }
unknown's avatar
unknown committed
3641
  }
3642

unknown's avatar
unknown committed
3643 3644
  # Default, no restart
  return 0;
3645 3646
}

unknown's avatar
unknown committed
3647

unknown's avatar
unknown committed
3648 3649 3650 3651
sub servers_need_restart($) {
  my ($tinfo)= @_;
  return grep { server_need_restart($tinfo, $_); } all_servers();
}
unknown's avatar
unknown committed
3652 3653 3654



unknown's avatar
unknown committed
3655 3656 3657 3658 3659 3660 3661 3662 3663 3664
#
# Return list of specific servers
#  - there is no servers in an empty config
#
sub _like   { return $config ? $config->like($_[0]) : (); }
sub mysqlds { return _like('mysqld.'); }
sub ndbds   { return _like('cluster_config.ndbd.');}
sub ndb_mgmds { return _like('cluster_config.ndb_mgmd.'); }
sub clusters  { return _like('mysql_cluster.'); }
sub all_servers { return ( mysqlds(), ndb_mgmds(), ndbds() ); }
unknown's avatar
unknown committed
3665 3666


unknown's avatar
unknown committed
3667 3668 3669 3670 3671 3672 3673 3674 3675
#
# Filter a list of servers and return only those that are part
# of the specified cluster
#
sub in_cluster {
  my ($cluster)= shift;
  # Return only processes for a specific cluster
  return grep { $_->suffix() eq $cluster->suffix() } @_;
}
unknown's avatar
unknown committed
3676

unknown's avatar
unknown committed
3677 3678


unknown's avatar
unknown committed
3679 3680 3681 3682 3683 3684
#
# Filter a list of servers and return the SafeProcess
# for only those that are started or stopped
#
sub started { return grep(defined $_, map($_->{proc}, @_));  }
sub stopped { return grep(!defined $_, map($_->{proc}, @_)); }
3685

unknown's avatar
unknown committed
3686

3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698
sub envsubst {
  my $string= shift;

  if ( ! defined $ENV{$string} )
  {
    mtr_error(".opt file references '$string' which is not set");
  }

  return $ENV{$string};
}


3699
sub get_extra_opts {
unknown's avatar
unknown committed
3700
  my ($mysqld, $tinfo)= @_;
unknown's avatar
unknown committed
3701

3702
  my $opts=
unknown's avatar
unknown committed
3703 3704
    $mysqld->option("#!use-slave-opt") ?
      $tinfo->{slave_opt} : $tinfo->{master_opt};
3705 3706 3707 3708 3709 3710 3711 3712

  # Expand environment variables
  foreach my $opt ( @$opts )
  {
    $opt =~ s/\$\{(\w+)\}/envsubst($1)/ge;
    $opt =~ s/\$(\w+)/envsubst($1)/ge;
  }
  return $opts;
unknown's avatar
unknown committed
3713
}
unknown's avatar
unknown committed
3714 3715


unknown's avatar
unknown committed
3716 3717
sub stop_servers($$) {
  my ($tinfo, @servers)= @_;
unknown's avatar
unknown committed
3718

unknown's avatar
unknown committed
3719 3720
  # Remember if we restarted for this test case (count restarts)
  $tinfo->{'restarted'}= 1;
unknown's avatar
unknown committed
3721

unknown's avatar
unknown committed
3722 3723 3724 3725
  if ( join('|', @servers) eq join('|', all_servers()) )
  {
    # All servers are going down, use some kind of order to
    # avoid too many warnings in the log files
unknown's avatar
unknown committed
3726

3727
   mtr_report("Restarting all servers");
3728

unknown's avatar
unknown committed
3729 3730
    #  mysqld processes
    My::SafeProcess::shutdown( $opt_shutdown_timeout, started(mysqlds()) );
3731

unknown's avatar
unknown committed
3732 3733 3734 3735 3736 3737
    # cluster processes
    My::SafeProcess::shutdown( $opt_shutdown_timeout,
			       started(ndbds(), ndb_mgmds()) );
  }
  else
  {
3738 3739
    mtr_report("Restarting ", started(@servers));

unknown's avatar
unknown committed
3740 3741 3742
     # Stop only some servers
    My::SafeProcess::shutdown( $opt_shutdown_timeout,
			       started(@servers) );
3743 3744
  }

unknown's avatar
unknown committed
3745
  foreach my $server (@servers)
unknown's avatar
unknown committed
3746
  {
unknown's avatar
unknown committed
3747 3748 3749 3750 3751 3752 3753
    # Mark server as stopped
    $server->{proc}= undef;

    # Forget history
    delete $server->{'started_tinfo'};
    delete $server->{'started_opts'};
    delete $server->{'started_cnf'};
unknown's avatar
unknown committed
3754
  }
unknown's avatar
unknown committed
3755 3756
}

3757

3758
#
unknown's avatar
unknown committed
3759
# start_servers
3760
#
unknown's avatar
unknown committed
3761
# Start servers not already started
3762 3763 3764 3765 3766
#
# RETURN
#  0 OK
#  1 Start failed
#
unknown's avatar
unknown committed
3767 3768
sub start_servers($) {
  my ($tinfo)= @_;
3769

unknown's avatar
unknown committed
3770 3771 3772 3773 3774
  # Start clusters
  foreach my $cluster ( clusters() )
  {
    ndbcluster_start($cluster);
  }
unknown's avatar
unknown committed
3775

unknown's avatar
unknown committed
3776 3777
  # Start mysqlds
  foreach my $mysqld ( mysqlds() )
unknown's avatar
unknown committed
3778
  {
unknown's avatar
unknown committed
3779
    if ( $mysqld->{proc} )
unknown's avatar
unknown committed
3780
    {
unknown's avatar
unknown committed
3781 3782 3783 3784 3785 3786
      # Already started

      # Write start of testcase to log file
      mark_log($mysqld->value('log-error'), $tinfo);

      next;
unknown's avatar
unknown committed
3787
    }
unknown's avatar
unknown committed
3788

unknown's avatar
unknown committed
3789 3790 3791 3792
    my $datadir= $mysqld->value('datadir');

    # Don't delete anything if starting dirty
    if (!$opt_start_dirty)
unknown's avatar
unknown committed
3793
    {
unknown's avatar
unknown committed
3794
      my @options= ('log-bin', 'relay-log');
unknown's avatar
unknown committed
3795

unknown's avatar
unknown committed
3796 3797
      foreach my $option_name ( @options )  {
	next unless $mysqld->option($option_name);
unknown's avatar
unknown committed
3798

unknown's avatar
unknown committed
3799
	my $value= $mysqld->value($option_name);
3800

unknown's avatar
unknown committed
3801
	foreach my $file ( glob("$datadir/$value*") )
3802
	{
unknown's avatar
unknown committed
3803 3804 3805
	  #print "removing: $file\n";
	  mtr_debug("Removing '$file'");
	  unlink($file);
3806
	}
unknown's avatar
unknown committed
3807
      }
unknown's avatar
unknown committed
3808 3809 3810 3811 3812

      # Remove old master.info and relay-log.info files
      # from the servers datadir
      unlink("$datadir/master.info");
      unlink("$datadir/relay-log.info");
unknown's avatar
unknown committed
3813
    }
unknown's avatar
unknown committed
3814

unknown's avatar
unknown committed
3815
    # Copy datadir from installed system db
3816 3817 3818 3819 3820 3821
    for my $path ( "$opt_vardir", "$opt_vardir/..") {
      my $install_db= "$path/install.db";
      copytree($install_db, $datadir)
	if -d $install_db;
    }
    mtr_error("Failed to copy system db to '$datadir'")
3822
      unless -d $datadir;
unknown's avatar
unknown committed
3823

3824 3825 3826 3827
    # Create the servers tmpdir
    my $tmpdir= $mysqld->value('tmpdir');
    mkpath($tmpdir) unless -d $tmpdir;

unknown's avatar
unknown committed
3828 3829
    # Write start of testcase to log file
    mark_log($mysqld->value('log-error'), $tinfo);
unknown's avatar
unknown committed
3830

unknown's avatar
unknown committed
3831 3832 3833
    # Run <tname>-master.sh
    if ($mysqld->option('#!run-master-sh') and
       run_sh_script($tinfo->{master_sh}) )
unknown's avatar
unknown committed
3834
    {
unknown's avatar
unknown committed
3835
      $tinfo->{'comment'}= "Failed to execute '$tinfo->{master_sh}'";
3836
      return 1;
unknown's avatar
unknown committed
3837
    }
unknown's avatar
unknown committed
3838

unknown's avatar
unknown committed
3839 3840 3841
    # Run <tname>-slave.sh
    if ($mysqld->option('#!run-slave-sh') and
	run_sh_script($tinfo->{slave_sh}))
unknown's avatar
unknown committed
3842
    {
unknown's avatar
unknown committed
3843 3844
      $tinfo->{'comment'}= "Failed to execute '$tinfo->{slave_sh}'";
      return 1;
unknown's avatar
unknown committed
3845 3846
    }

unknown's avatar
unknown committed
3847 3848 3849 3850 3851 3852 3853 3854
    if (!$opt_embedded_server)
    {
      my $extra_opts= get_extra_opts($mysqld, $tinfo);
      mysqld_start($mysqld,$extra_opts);

      # Save this test case information, so next can examine it
      $mysqld->{'started_tinfo'}= $tinfo;
    }
3855

unknown's avatar
unknown committed
3856 3857
  }

3858
  # Wait for clusters to start
unknown's avatar
unknown committed
3859
  foreach my $cluster ( clusters() )
unknown's avatar
unknown committed
3860
  {
3861
    if (ndbcluster_wait_started($cluster, ""))
3862 3863
    {
      # failed to start
unknown's avatar
unknown committed
3864
      $tinfo->{'comment'}= "Start of '".$cluster->name()."' cluster failed";
3865
      return 1;
3866
    }
unknown's avatar
unknown committed
3867 3868
  }

unknown's avatar
unknown committed
3869 3870
  # Wait for mysqlds to start
  foreach my $mysqld ( mysqlds() )
3871
  {
unknown's avatar
unknown committed
3872 3873
    next if !started($mysqld);

unknown's avatar
unknown committed
3874 3875 3876 3877 3878
    if (sleep_until_file_created($mysqld->value('pid-file'),
				 $opt_start_timeout,
				 $mysqld->{'proc'}) == 0) {
      $tinfo->{comment}=
	"Failed to start ".$mysqld->name();
3879
      return 1;
3880
    }
unknown's avatar
unknown committed
3881
  }
3882
  return 0;
unknown's avatar
unknown committed
3883 3884
}

unknown's avatar
unknown committed
3885

3886 3887
#
# Run include/check-testcase.test
unknown's avatar
unknown committed
3888
# Before a testcase, run in record mode and save result file to var/tmp
3889 3890
# After testcase, run and compare with the recorded file, they should be equal!
#
3891
# RETURN VALUE
3892
#  The newly started process
3893
#
3894
sub start_check_testcase ($$$) {
unknown's avatar
unknown committed
3895
  my $tinfo=    shift;
3896
  my $mode=     shift;
3897 3898
  my $mysqld=   shift;

unknown's avatar
unknown committed
3899 3900
  my $name= "check-".$mysqld->name();
  my $tname= $tinfo->{name};
3901 3902 3903 3904

  my $args;
  mtr_init_args(\$args);

3905 3906 3907
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
  mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));

3908 3909 3910
  mtr_add_arg($args, "--silent");
  mtr_add_arg($args, "--skip-safemalloc");

unknown's avatar
unknown committed
3911 3912
  mtr_add_arg($args, "--result-file=%s", "$opt_vardir/tmp/$name.result");
  mtr_add_arg($args, "--test-file=%s", "include/check-testcase.test");
3913 3914 3915 3916 3917

  if ( $mode eq "before" )
  {
    mtr_add_arg($args, "--record");
  }
unknown's avatar
unknown committed
3918
  my $errfile= "$opt_vardir/tmp/$name.err";
3919
  my $proc= My::SafeProcess->new
unknown's avatar
unknown committed
3920 3921 3922 3923 3924
    (
     name          => $name,
     path          => $exe_mysqltest,
     error         => $errfile,
     args          => \$args,
3925
     user_data     => $errfile,
unknown's avatar
unknown committed
3926
    );
3927

3928 3929
  mtr_report("Started $proc");
  return $proc;
3930 3931
}

3932

unknown's avatar
unknown committed
3933 3934 3935
sub run_mysqltest ($) {
  my $proc= start_mysqltest(@_);
  $proc->wait();
3936
}
unknown's avatar
unknown committed
3937

3938

unknown's avatar
unknown committed
3939
sub start_mysqltest ($) {
3940
  my ($tinfo)= @_;
unknown's avatar
unknown committed
3941 3942
  my $exe= $exe_mysqltest;
  my $args;
unknown's avatar
unknown committed
3943 3944 3945

  mtr_init_args(\$args);

unknown's avatar
unknown committed
3946
  mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
unknown's avatar
unknown committed
3947 3948 3949
  mtr_add_arg($args, "--silent");
  mtr_add_arg($args, "--skip-safemalloc");
  mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
3950
  mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
3951
  mtr_add_arg($args, "--logdir=%s/log", $opt_vardir);
3952

3953 3954 3955 3956
  # Log line number and time  for each line in .test file
  mtr_add_arg($args, "--mark-progress")
    if $opt_mark_progress;

unknown's avatar
unknown committed
3957
  mtr_add_arg($args, "--database=test");
unknown's avatar
unknown committed
3958

unknown's avatar
unknown committed
3959 3960 3961 3962 3963
  if ( $opt_ps_protocol )
  {
    mtr_add_arg($args, "--ps-protocol");
  }

3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978
  if ( $opt_sp_protocol )
  {
    mtr_add_arg($args, "--sp-protocol");
  }

  if ( $opt_view_protocol )
  {
    mtr_add_arg($args, "--view-protocol");
  }

  if ( $opt_cursor_protocol )
  {
    mtr_add_arg($args, "--cursor-protocol");
  }

unknown's avatar
unknown committed
3979 3980
  if ( $opt_strace_client )
  {
unknown's avatar
unknown committed
3981
    $exe=  $opt_strace_client || "strace";
unknown's avatar
unknown committed
3982
    mtr_add_arg($args, "-o");
3983
    mtr_add_arg($args, "%s/log/mysqltest.strace", $opt_vardir);
unknown's avatar
unknown committed
3984 3985 3986
    mtr_add_arg($args, "$exe_mysqltest");
  }

unknown's avatar
unknown committed
3987
  mtr_add_arg($args, "--timer-file=%s/log/timer", $opt_vardir);
unknown's avatar
unknown committed
3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998

  if ( $opt_compress )
  {
    mtr_add_arg($args, "--compress");
  }

  if ( $opt_sleep )
  {
    mtr_add_arg($args, "--sleep=%d", $opt_sleep);
  }

unknown's avatar
unknown committed
3999
  client_debug_arg($args, "mysqltest");
4000 4001 4002

  if ( $opt_ssl )
  {
4003
    # Turn on SSL for _all_ test cases if option --ssl was used
4004
    mtr_add_arg($args, "--ssl");
4005
  }
unknown's avatar
unknown committed
4006 4007 4008 4009 4010
  elsif ( $opt_ssl_supported )
  {
    mtr_add_arg($args, "--skip-ssl");
  }

unknown's avatar
unknown committed
4011 4012 4013 4014 4015 4016
  if ( $opt_embedded_server )
  {

    # Get the args needed for the embedded server
    # and append them to args prefixed
    # with --sever-arg=
unknown's avatar
unknown committed
4017

unknown's avatar
unknown committed
4018 4019 4020 4021 4022 4023 4024 4025 4026
    my $mysqld=  $config->group('embedded')
      or mtr_error("Could not get [embedded] section");

    my $mysqld_args;
    mtr_init_args(\$mysqld_args);
    my $extra_opts= get_extra_opts($mysqld, $tinfo);
    mysqld_arguments($mysqld_args, $mysqld, $extra_opts);
    mtr_add_arg($args, "--server-arg=%s", $_) for @$mysqld_args;
  }
unknown's avatar
unknown committed
4027

4028 4029 4030
  # ----------------------------------------------------------------------
  # export MYSQL_TEST variable containing <path>/mysqltest <args>
  # ----------------------------------------------------------------------
unknown's avatar
unknown committed
4031
  $ENV{'MYSQL_TEST'}= mtr_args2str($exe_mysqltest, @$args);
4032

4033
  # ----------------------------------------------------------------------
4034
  # Add arguments that should not go into the MYSQL_TEST env var
4035
  # ----------------------------------------------------------------------
4036
  if ( $opt_valgrind_mysqltest )
4037 4038 4039 4040 4041 4042 4043 4044 4045 4046
  {
    # Prefix the Valgrind options to the argument list.
    # We do this here, since we do not want to Valgrind the nested invocations
    # of mysqltest; that would mess up the stderr output causing test failure.
    my @args_saved = @$args;
    mtr_init_args(\$args);
    valgrind_arguments($args, \$exe);
    mtr_add_arg($args, "%s", $_) for @args_saved;
  }

4047
  mtr_add_arg($args, "--test-file=%s", $tinfo->{'path'});
unknown's avatar
unknown committed
4048

4049 4050 4051
  # Number of lines of resut to include in failure report
  mtr_add_arg($args, "--tail-lines=20");

4052
  if ( defined $tinfo->{'result_file'} ) {
4053
    mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'});
4054
  }
4055 4056 4057 4058 4059 4060

  if ( $opt_record )
  {
    mtr_add_arg($args, "--record");
  }

unknown's avatar
unknown committed
4061 4062 4063 4064 4065 4066 4067 4068
  if ( $opt_client_gdb )
  {
    gdb_arguments(\$args, \$exe, "client");
  }
  elsif ( $opt_client_ddd )
  {
    ddd_arguments(\$args, \$exe, "client");
  }
4069 4070 4071
  elsif ( $opt_client_debugger )
  {
    debugger_arguments(\$args, \$exe, "client");
unknown's avatar
unknown committed
4072
 }
4073 4074


unknown's avatar
unknown committed
4075 4076 4077 4078 4079
  my $proc= My::SafeProcess->new
    (
     name          => "mysqltest",
     path          => $exe,
     args          => \$args,
4080 4081
     append        => 1,
     error         => $path_current_testlog,
unknown's avatar
unknown committed
4082 4083 4084 4085
     verbose       => $opt_verbose,
    );
  mtr_verbose("Started $proc");
  return $proc;
unknown's avatar
unknown committed
4086
}
unknown's avatar
unknown committed
4087

unknown's avatar
unknown committed
4088

unknown's avatar
unknown committed
4089 4090 4091 4092 4093 4094 4095 4096 4097 4098
#
# Modify the exe and args so that program is run in gdb in xterm
#
sub gdb_arguments {
  my $args= shift;
  my $exe=  shift;
  my $type= shift;

  # Write $args to gdb init file
  my $str= join(" ", @$$args);
4099
  my $gdb_init_file= "$opt_vardir/tmp/gdbinit.$type";
unknown's avatar
unknown committed
4100

4101 4102 4103
  # Remove the old gdbinit file
  unlink($gdb_init_file);

unknown's avatar
unknown committed
4104 4105 4106 4107
  if ( $type eq "client" )
  {
    # write init file for client
    mtr_tofile($gdb_init_file,
4108 4109
	       "set args $str\n" .
	       "break main\n");
unknown's avatar
unknown committed
4110 4111 4112 4113 4114 4115 4116 4117 4118 4119
  }
  else
  {
    # write init file for mysqld
    mtr_tofile($gdb_init_file,
	       "set args $str\n" .
	       "break mysql_parse\n" .
	       "commands 1\n" .
	       "disable 1\n" .
	       "end\n" .
4120 4121 4122 4123 4124
	       "run");
  }

  if ( $opt_manual_gdb )
  {
4125
     print "\nTo start gdb for $type, type in another window:\n";
unknown's avatar
unknown committed
4126
     print "gdb -cd $glob_mysql_test_dir -x $gdb_init_file $$exe\n";
4127 4128 4129 4130

     # Indicate the exe should not be started
     $$exe= undef;
     return;
unknown's avatar
unknown committed
4131 4132 4133 4134 4135 4136
  }

  $$args= [];
  mtr_add_arg($$args, "-title");
  mtr_add_arg($$args, "$type");
  mtr_add_arg($$args, "-e");
4137

4138
  if ( $exe_libtool )
unknown's avatar
unknown committed
4139
  {
4140
    mtr_add_arg($$args, $exe_libtool);
unknown's avatar
unknown committed
4141 4142 4143 4144 4145 4146 4147 4148 4149
    mtr_add_arg($$args, "--mode=execute");
  }

  mtr_add_arg($$args, "gdb");
  mtr_add_arg($$args, "-x");
  mtr_add_arg($$args, "$gdb_init_file");
  mtr_add_arg($$args, "$$exe");

  $$exe= "xterm";
unknown's avatar
unknown committed
4150
}
unknown's avatar
unknown committed
4151

unknown's avatar
unknown committed
4152

unknown's avatar
unknown committed
4153 4154 4155 4156 4157 4158 4159 4160 4161 4162
#
# Modify the exe and args so that program is run in ddd
#
sub ddd_arguments {
  my $args= shift;
  my $exe=  shift;
  my $type= shift;

  # Write $args to ddd init file
  my $str= join(" ", @$$args);
4163
  my $gdb_init_file= "$opt_vardir/tmp/gdbinit.$type";
unknown's avatar
unknown committed
4164

4165 4166 4167
  # Remove the old gdbinit file
  unlink($gdb_init_file);

unknown's avatar
unknown committed
4168 4169 4170 4171 4172
  if ( $type eq "client" )
  {
    # write init file for client
    mtr_tofile($gdb_init_file,
	       "set args $str\n" .
4173
	       "break main\n");
unknown's avatar
unknown committed
4174 4175 4176 4177 4178 4179 4180 4181 4182 4183
  }
  else
  {
    # write init file for mysqld
    mtr_tofile($gdb_init_file,
	       "file $$exe\n" .
	       "set args $str\n" .
	       "break mysql_parse\n" .
	       "commands 1\n" .
	       "disable 1\n" .
4184
	       "end");
4185 4186 4187 4188
  }

  if ( $opt_manual_ddd )
  {
4189
     print "\nTo start ddd for $type, type in another window:\n";
unknown's avatar
unknown committed
4190
     print "ddd -cd $glob_mysql_test_dir -x $gdb_init_file $$exe\n";
4191 4192 4193 4194

     # Indicate the exe should not be started
     $$exe= undef;
     return;
unknown's avatar
unknown committed
4195
  }
unknown's avatar
unknown committed
4196

unknown's avatar
unknown committed
4197 4198
  my $save_exe= $$exe;
  $$args= [];
4199
  if ( $exe_libtool )
unknown's avatar
unknown committed
4200
  {
4201
    $$exe= $exe_libtool;
unknown's avatar
unknown committed
4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212
    mtr_add_arg($$args, "--mode=execute");
    mtr_add_arg($$args, "ddd");
  }
  else
  {
    $$exe= "ddd";
  }
  mtr_add_arg($$args, "--command=$gdb_init_file");
  mtr_add_arg($$args, "$save_exe");
}

4213 4214 4215 4216 4217 4218 4219 4220 4221

#
# Modify the exe and args so that program is run in the selected debugger
#
sub debugger_arguments {
  my $args= shift;
  my $exe=  shift;
  my $debugger= $opt_debugger || $opt_client_debugger;

4222
  if ( $debugger =~ /vcexpress|vc|devenv/ )
4223 4224 4225 4226 4227 4228 4229
  {
    # vc[express] /debugexe exe arg1 .. argn

    # Add /debugexe and name of the exe before args
    unshift(@$$args, "/debugexe");
    unshift(@$$args, "$$exe");

4230 4231 4232
    # Set exe to debuggername
    $$exe= $debugger;

4233
  }
4234
  elsif ( $debugger =~ /windbg/ )
4235 4236 4237 4238 4239 4240
  {
    # windbg exe arg1 .. argn

    # Add name of the exe before args
    unshift(@$$args, "$$exe");

4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255
    # Set exe to debuggername
    $$exe= $debugger;

  }
  elsif ( $debugger eq "dbx" )
  {
    # xterm -e dbx -r exe arg1 .. argn

    unshift(@$$args, $$exe);
    unshift(@$$args, "-r");
    unshift(@$$args, $debugger);
    unshift(@$$args, "-e");

    $$exe= "xterm";

4256 4257 4258 4259 4260 4261 4262 4263
  }
  else
  {
    mtr_error("Unknown argument \"$debugger\" passed to --debugger");
  }
}


unknown's avatar
unknown committed
4264 4265 4266
#
# Modify the exe and args so that program is run in valgrind
#
unknown's avatar
unknown committed
4267 4268 4269 4270
sub valgrind_arguments {
  my $args= shift;
  my $exe=  shift;

4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284
  if ( $opt_callgrind)
  {
    mtr_add_arg($args, "--tool=callgrind");
    mtr_add_arg($args, "--base=$opt_vardir/log");
  }
  else
  {
    mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
    mtr_add_arg($args, "--alignment=8");
    mtr_add_arg($args, "--leak-check=yes");
    mtr_add_arg($args, "--num-callers=16");
    mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)
      if -f "$glob_mysql_test_dir/valgrind.supp";
  }
unknown's avatar
unknown committed
4285

4286
  # Add valgrind options, can be overriden by user
unknown's avatar
unknown committed
4287
  mtr_add_arg($args, '%s', $_) for (@valgrind_args);
4288

unknown's avatar
unknown committed
4289 4290
  mtr_add_arg($args, $$exe);

unknown's avatar
unknown committed
4291
  $$exe= $opt_valgrind_path || "valgrind";
4292 4293 4294 4295 4296 4297 4298 4299

  if ($exe_libtool)
  {
    # Add "libtool --mode-execute" before the test to execute
    # if running in valgrind(to avoid valgrinding bash)
    unshift(@$args, "--mode=execute", $$exe);
    $$exe= $exe_libtool;
  }
unknown's avatar
unknown committed
4300 4301 4302
}


unknown's avatar
unknown committed
4303
#
unknown's avatar
unknown committed
4304
# Usage
unknown's avatar
unknown committed
4305
#
unknown's avatar
unknown committed
4306
sub usage ($) {
4307 4308 4309 4310
  my $message= shift;

  if ( $message )
  {
unknown's avatar
unknown committed
4311
    print STDERR "$message\n";
4312 4313
  }

unknown's avatar
unknown committed
4314
  print <<HERE;
unknown's avatar
unknown committed
4315

unknown's avatar
unknown committed
4316
$0 [ OPTIONS ] [ TESTCASE ]
unknown's avatar
unknown committed
4317 4318 4319 4320 4321

Options to control what engine/variation to run

  embedded-server       Use the embedded server, i.e. no mysqld daemons
  ps-protocol           Use the binary protocol between client and server
4322 4323 4324 4325
  cursor-protocol       Use the cursor protocol between client and server
                        (implies --ps-protocol)
  view-protocol         Create a view to execute all non updating queries
  sp-protocol           Create a stored procedure to execute all queries
4326 4327
  compress              Use the compressed protocol between client and server
  ssl                   Use ssl protocol between client and server
4328
  skip-ssl              Dont start server with support for ssl connections
4329
  ndb|with-ndbcluster   Use cluster as default table type
4330 4331
  vs-config             Visual Studio configuration used to create executables
                        (default: MTR_VS_CONFIG environment variable)
unknown's avatar
unknown committed
4332

unknown's avatar
unknown committed
4333 4334
  config|defaults-file=<config template> Use fixed config template for all
                        tests
4335
  defaults_extra_file=<config template> Extra config template to add to
unknown's avatar
unknown committed
4336 4337
                        all generated configs

4338 4339 4340
Options to control directories to use
  tmpdir=DIR            The directory where temporary files are stored
                        (default: ./var/tmp).
4341 4342 4343
  vardir=DIR            The directory where files generated from the test run
                        is stored (default: ./var). Specifying a ramdisk or
                        tmpfs will speed up tests.
4344 4345 4346
  mem                   Run testsuite in "memory" using tmpfs or ramdisk
                        Attempts to find a suitable location
                        using a builtin list of standard locations
4347 4348 4349
                        for tmpfs (/dev/shm)
                        The option can also be set using environment
                        variable MTR_MEM=[DIR]
unknown's avatar
unknown committed
4350 4351 4352
  client-bindir=PATH    Path to the directory where client binaries are located
  client-libdir=PATH    Path to the directory where client libraries are located

4353

unknown's avatar
unknown committed
4354 4355 4356
Options to control what test suites or cases to run

  force                 Continue to run the suite after failure
4357
  with-ndbcluster-only  Run only tests that include "ndb" in the filename
unknown's avatar
unknown committed
4358 4359
  skip-ndb[cluster]     Skip all tests that need cluster
  skip-ndb[cluster]-slave Skip all tests that need a slave cluster
4360 4361 4362 4363 4364 4365
  do-test=PREFIX or REGEX
                        Run test cases which name are prefixed with PREFIX
                        or fulfills REGEX
  skip-test=PREFIX or REGEX
                        Skip test cases which name are prefixed with PREFIX
                        or fulfills REGEX
4366 4367 4368 4369
  start-from=PREFIX     Run test cases starting test prefixed with PREFIX where
                        prefix may be suite.testname or just testname
  suite[s]=NAME1,..,NAMEN
                        Collect tests in suites from the comma separated
4370
                        list of suite names.
4371
                        The default is: "$DEFAULT_SUITES"
unknown's avatar
unknown committed
4372
  skip-rpl              Skip the replication test cases.
4373 4374
  big-test              Set the environment variable BIG_TEST, which can be
                        checked from test cases.
unknown's avatar
unknown committed
4375 4376 4377

Options that specify ports

unknown's avatar
unknown committed
4378
  mtr-build-thread=#    Specify unique number to calculate port number(s) from.
unknown's avatar
unknown committed
4379
  build-thread=#        Can be set in environment variable MTR_BUILD_THREAD.
unknown's avatar
unknown committed
4380 4381
                        Set  MTR_BUILD_THREAD="auto" to automatically aquire
                        a build thread id that is unique to current host
unknown's avatar
unknown committed
4382 4383 4384 4385

Options for test case authoring

  record TESTNAME       (Re)genereate the result file for TESTNAME
4386
  check-testcases       Check testcases for sideeffects
4387
  mark-progress         Log line number and elapsed time to <testname>.progress
unknown's avatar
unknown committed
4388 4389 4390 4391 4392 4393 4394

Options that pass on options

  mysqld=ARGS           Specify additional arguments to "mysqld"

Options to run test on running server

unknown's avatar
unknown committed
4395 4396 4397 4398 4399 4400
  extern option=value   Run only the tests against an already started server
                        the options to use for connection to the extern server
                        must be specified using name-value pair notation
                        For example:
                         ./$0 --extern socket=/tmp/mysqld.sock

4401 4402
  user=USER             User for connection to extern server
  socket=PATH           Socket for connection to extern server
unknown's avatar
unknown committed
4403 4404 4405

Options for debugging the product

4406 4407
  client-ddd            Start mysqltest client in ddd
  client-debugger=NAME  Start mysqltest in the selected debugger
unknown's avatar
unknown committed
4408 4409
  client-gdb            Start mysqltest client in gdb
  ddd                   Start mysqld in ddd
4410
  debug                 Dump trace output for all servers and client programs
4411
  debugger=NAME         Start mysqld in the selected debugger
4412 4413 4414 4415 4416
  gdb                   Start the mysqld(s) in gdb
  manual-debug          Let user manually start mysqld in debugger, before
                        running test(s)
  manual-gdb            Let user manually start mysqld in gdb, before running
                        test(s)
unknown's avatar
unknown committed
4417 4418
  manual-ddd            Let user manually start mysqld in ddd, before running
                        test(s)
unknown's avatar
unknown committed
4419 4420 4421
  strace-client=[path]  Create strace output for mysqltest client, optionally
                        specifying name and path to the trace program to use.
                        Example: $0 --strace-client=ktrace
4422 4423
  max-save-core         Limit the number of core files saved (to avoid filling
                        up disks for heavily crashing server). Defaults to
4424 4425 4426 4427 4428 4429
                        $opt_max_save_core, set to 0 for no limit. Set
                        it's default with MTR_MAX_SAVE_CORE
  max-save-datadir      Limit the number of datadir saved (to avoid filling
                        up disks for heavily crashing server). Defaults to
                        $opt_max_save_datadir, set to 0 for no limit. Set
                        it's default with MTR_MAX_SAVE_DATDIR
4430 4431 4432 4433
  max-test-fail         Limit the number of test failurs before aborting
                        the current test run. Defaults to
                        $opt_max_test_fail, set to 0 for no limit. Set
                        it's default with MTR_MAX_TEST_FAIL
unknown's avatar
unknown committed
4434

unknown's avatar
unknown committed
4435
Options for valgrind
unknown's avatar
unknown committed
4436

4437
  valgrind              Run the "mysqltest" and "mysqld" executables using
unknown's avatar
unknown committed
4438
                        valgrind with default options
4439
  valgrind-all          Synonym for --valgrind
4440 4441
  valgrind-mysqltest    Run the "mysqltest" and "mysql_client_test" executable
                        with valgrind
unknown's avatar
unknown committed
4442
  valgrind-mysqld       Run the "mysqld" executable with valgrind
unknown's avatar
unknown committed
4443 4444 4445
  valgrind-options=ARGS Deprecated, use --valgrind-option
  valgrind-option=ARGS  Option to give valgrind, replaces default option(s),
                        can be specified more then once
unknown's avatar
unknown committed
4446
  valgrind-path=[EXE]   Path to the valgrind executable
4447
  callgrind             Instruct valgrind to use callgrind
unknown's avatar
unknown committed
4448 4449 4450

Misc options

4451
  comment=STR           Write STR to the output
4452
  notimer               Don't show test case execution time
unknown's avatar
unknown committed
4453 4454 4455 4456 4457
  verbose               More verbose output(use multiple times for even more)
  start                 Only initialize and start the servers, using the
                        startup settings for the first specified test case
                        Example:
                         $0 --start alias &
4458
  start-dirty           Only start the servers (without initialization) for
unknown's avatar
unknown committed
4459 4460 4461
                        the first specified test case
  fast                  Run as fast as possible, dont't wait for servers
                        to shutdown etc.
unknown's avatar
unknown committed
4462 4463
  repeat=N              Run each test N number of times
  retry=N               Retry tests that fail N times, limit number of failures
unknown's avatar
unknown committed
4464
                        to $opt_retry_failure
unknown's avatar
unknown committed
4465
  retry-failure=N       Limit number of retries for a failed test
4466
  reorder               Reorder tests to get fewer server restarts
unknown's avatar
unknown committed
4467 4468
  help                  Get this help text

unknown's avatar
unknown committed
4469 4470 4471 4472 4473 4474
  testcase-timeout=MINUTES Max test case run time (default $opt_testcase_timeout)
  suite-timeout=MINUTES Max test suite run time (default $opt_suite_timeout)
  shutdown-timeout=SECONDS Max number of seconds to wait for server shutdown
                        before killing servers (default $opt_shutdown_timeout)
  warnings              Scan the log files for warnings. Use --nowarnings
                        to turn off.
4475

4476
  sleep=SECONDS         Passed to mysqltest, will be used as fixed sleep time
unknown's avatar
unknown committed
4477

unknown's avatar
unknown committed
4478
HERE
unknown's avatar
unknown committed
4479
  exit(1);
4480

unknown's avatar
unknown committed
4481
}
unknown's avatar
unknown committed
4482