summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/lib/mtr_cases.pl365
-rw-r--r--mysql-test/lib/mtr_im.pl761
-rw-r--r--mysql-test/lib/mtr_io.pl66
-rw-r--r--mysql-test/lib/mtr_misc.pl40
-rw-r--r--mysql-test/lib/mtr_process.pl675
-rw-r--r--mysql-test/lib/mtr_report.pl137
-rw-r--r--mysql-test/lib/mtr_stress.pl178
-rwxr-xr-xmysql-test/mysql-test-run.pl3631
-rw-r--r--mysql-test/r/mysqltest.result2
9 files changed, 4569 insertions, 1286 deletions
diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl
index 650fb79155d..bb92730444c 100644
--- a/mysql-test/lib/mtr_cases.pl
+++ b/mysql-test/lib/mtr_cases.pl
@@ -5,10 +5,13 @@
# same name.
use File::Basename;
+use IO::File();
use strict;
sub collect_test_cases ($);
-sub collect_one_test_case ($$$$$$);
+sub collect_one_test_case ($$$$$$$);
+
+sub mtr_options_from_test_file($$);
##############################################################################
#
@@ -37,44 +40,114 @@ sub collect_test_cases ($) {
opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");
+ # ----------------------------------------------------------------------
+ # Disable some tests listed in disabled.def
+ # ----------------------------------------------------------------------
+ my %disabled;
+ if ( open(DISABLED, "$testdir/disabled.def" ) )
+ {
+ while ( <DISABLED> )
+ {
+ chomp;
+ if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
+ {
+ $disabled{$1}= $2;
+ }
+ }
+ close DISABLED;
+ }
+
if ( @::opt_cases )
{
foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
- $tname= basename($tname, ".test");
- my $elem= "$tname.test";
- if ( ! -f "$testdir/$elem")
+ my $elem= undef;
+ my $component_id= undef;
+
+ # Get rid of directory part (path). Leave the extension since it is used
+ # to understand type of the test.
+
+ $tname = basename($tname);
+
+ # Check if the extenstion has been specified.
+
+ if ( mtr_match_extension($tname, "test") )
+ {
+ $elem= $tname;
+ $tname=~ s/\.test$//;
+ $component_id= 'mysqld';
+ }
+ elsif ( mtr_match_extension($tname, "imtest") )
+ {
+ $elem= $tname;
+ $tname =~ s/\.imtest$//;
+ $component_id= 'im';
+ }
+
+ # If target component is known, check that the specified test case
+ # exists.
+ #
+ # Otherwise, try to guess the target component.
+
+ if ( $component_id )
+ {
+ if ( ! -f "$testdir/$elem")
+ {
+ mtr_error("Test case $tname ($testdir/$elem) is not found");
+ }
+ }
+ else
{
- mtr_error("Test case $tname ($testdir/$elem) is not found");
+ my $mysqld_test_exists = -f "$testdir/$tname.test";
+ my $im_test_exists = -f "$testdir/$tname.imtest";
+
+ if ( $mysqld_test_exists and $im_test_exists )
+ {
+ mtr_error("Ambiguous test case name ($tname)");
+ }
+ elsif ( ! $mysqld_test_exists and ! $im_test_exists )
+ {
+ mtr_error("Test case $tname is not found");
+ }
+ elsif ( $mysqld_test_exists )
+ {
+ $elem= "$tname.test";
+ $component_id= 'mysqld';
+ }
+ elsif ( $im_test_exists )
+ {
+ $elem= "$tname.imtest";
+ $component_id= 'im';
+ }
}
- collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{});
+
+ collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
+ $component_id);
}
closedir TESTDIR;
}
else
{
- # ----------------------------------------------------------------------
- # Disable some tests listed in disabled.def
- # ----------------------------------------------------------------------
- my %disabled;
- if ( open(DISABLED, "$testdir/disabled.def" ) )
- {
- while ( <DISABLED> )
+ foreach my $elem ( sort readdir(TESTDIR) ) {
+ my $component_id= undef;
+ my $tname= undef;
+
+ if ($tname= mtr_match_extension($elem, 'test'))
{
- chomp;
- if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
- {
- $disabled{$1}= $2;
- }
+ $component_id = 'mysqld';
}
- close DISABLED;
- }
-
- foreach my $elem ( sort readdir(TESTDIR) ) {
- my $tname= mtr_match_extension($elem,"test");
- next if ! defined $tname;
+ elsif ($tname= mtr_match_extension($elem, 'imtest'))
+ {
+ $component_id = 'im';
+ }
+ else
+ {
+ next;
+ }
+
next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test);
- collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled);
+ collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
+ $component_id);
}
closedir TESTDIR;
}
@@ -84,34 +157,38 @@ sub collect_test_cases ($) {
if ( $::opt_reorder )
{
- @$cases = sort {
- if ( ! $a->{'master_restart'} and ! $b->{'master_restart'} )
- {
- return $a->{'name'} cmp $b->{'name'};
- }
- if ( $a->{'master_restart'} and $b->{'master_restart'} )
- {
- my $cmp= mtr_cmp_opts($a->{'master_opt'}, $b->{'master_opt'});
- if ( $cmp == 0 )
- {
- return $a->{'name'} cmp $b->{'name'};
- }
- else
- {
- return $cmp;
- }
- }
+ my %sort_criteria;
+ my $tinfo;
- if ( $a->{'master_restart'} )
- {
- return 1; # Is greater
- }
- else
- {
- return -1; # Is less
- }
- } @$cases;
+ # Make a mapping of test name to a string that represents how that test
+ # should be sorted among the other tests. Put the most important criterion
+ # first, then a sub-criterion, then sub-sub-criterion, et c.
+ foreach $tinfo (@$cases)
+ {
+ my @this_criteria = ();
+
+ # Append the criteria for sorting, in order of importance.
+ push(@this_criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~"); # Ending with "~" makes empty sort later than filled
+ push(@this_criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0"));
+ push(@this_criteria, "restart=" . ($tinfo->{'master_restart'} ? "1" : "0"));
+ push(@this_criteria, "big_test=" . ($tinfo->{'big_test'} ? "1" : "0"));
+ push(@this_criteria, join("|", sort keys %{$tinfo})); # Group similar things together. The values may differ substantially. FIXME?
+ push(@this_criteria, $tinfo->{'name'}); # Finally, order by the name
+
+ $sort_criteria{$tinfo->{"name"}} = join(" ", @this_criteria);
+ }
+
+ @$cases = sort { $sort_criteria{$a->{"name"}} cmp $sort_criteria{$b->{"name"}}; } @$cases;
+
+### For debugging the sort-order
+# foreach $tinfo (@$cases)
+# {
+# print $sort_criteria{$tinfo->{"name"}};
+# print " -> \t";
+# print $tinfo->{"name"};
+# print "\n";
+# }
}
return $cases;
@@ -125,13 +202,14 @@ sub collect_test_cases ($) {
##############################################################################
-sub collect_one_test_case($$$$$$) {
+sub collect_one_test_case($$$$$$$) {
my $testdir= shift;
my $resdir= shift;
my $tname= shift;
my $elem= shift;
my $cases= shift;
my $disabled=shift;
+ my $component_id= shift;
my $path= "$testdir/$elem";
@@ -151,6 +229,7 @@ sub collect_one_test_case($$$$$$) {
my $tinfo= {};
$tinfo->{'name'}= $tname;
$tinfo->{'result_file'}= "$resdir/$tname.result";
+ $tinfo->{'component_id'} = $component_id;
push(@$cases, $tinfo);
if ( $::opt_skip_test and defined mtr_match_prefix($tname,$::opt_skip_test) )
@@ -171,48 +250,54 @@ sub collect_one_test_case($$$$$$) {
if ( $::opt_skip_rpl )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No replication tests(--skip-rpl)";
return;
}
$tinfo->{'slave_num'}= 1; # Default, use one slave
- # FIXME currently we always restart slaves
- $tinfo->{'slave_restart'}= 1;
-
if ( $tname eq 'rpl_failsafe' or $tname eq 'rpl_chain_temp_table' )
{
-# $tinfo->{'slave_num'}= 3; # Not 3 ? Check old code, strange
+ # $tinfo->{'slave_num'}= 3; # Not 3 ? Check old code, strange
}
}
if ( defined mtr_match_prefix($tname,"federated") )
{
- $tinfo->{'slave_num'}= 1; # Default, use one slave
-
- # FIXME currently we always restart slaves
- $tinfo->{'slave_restart'}= 1;
+ # Default, federated uses the first slave as it's federated database
+ $tinfo->{'slave_num'}= 1;
}
- # Cluster is needed by test case if testname contains ndb
- if ( defined mtr_match_substring($tname,"ndb") )
+ if ( $::opt_with_ndbcluster or defined mtr_match_substring($tname,"ndb") )
{
+ # This is an ndb test or all tests should be run with ndb cluster started
$tinfo->{'ndb_test'}= 1;
if ( $::opt_skip_ndbcluster )
{
- # Skip all ndb tests
+ # All ndb test's should be skipped
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No ndbcluster test(--skip-ndbcluster)";
return;
}
- if ( ! $::opt_with_ndbcluster )
+ if ( ! $::opt_ndbcluster_supported )
{
# Ndb is not supported, skip them
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No ndbcluster support";
return;
}
}
else
{
+ # This is not a ndb test
$tinfo->{'ndb_test'}= 0;
+ if ( $::opt_with_ndbcluster_only )
+ {
+ # Only the ndb test should be run, all other should be skipped
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Only ndbcluster tests(--with-ndbcluster-only)";
+ return;
+ }
}
# FIXME what about embedded_server + ndbcluster, skip ?!
@@ -223,6 +308,7 @@ sub collect_one_test_case($$$$$$) {
my $master_sh= "$testdir/$tname-master.sh";
my $slave_sh= "$testdir/$tname-slave.sh";
my $disabled_file= "$testdir/$tname.disabled";
+ my $im_opt_file= "$testdir/$tname-im.opt";
$tinfo->{'master_opt'}= [];
$tinfo->{'slave_opt'}= [];
@@ -303,6 +389,8 @@ sub collect_one_test_case($$$$$$) {
if ( $::glob_win32_perl )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No tests with sh scripts on Windows";
+ return;
}
else
{
@@ -316,6 +404,8 @@ sub collect_one_test_case($$$$$$) {
if ( $::glob_win32_perl )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No tests with sh scripts on Windows";
+ return;
}
else
{
@@ -324,29 +414,166 @@ sub collect_one_test_case($$$$$$) {
}
}
+ if ( -f $im_opt_file )
+ {
+ $tinfo->{'im_opts'} = mtr_get_opts_from_file($im_opt_file);
+ }
+ else
+ {
+ $tinfo->{'im_opts'} = [];
+ }
+
# FIXME why this late?
+ my $marked_as_disabled= 0;
if ( $disabled->{$tname} )
{
- $tinfo->{'skip'}= 1;
- $tinfo->{'disable'}= 1; # Sub type of 'skip'
- $tinfo->{'comment'}= $disabled->{$tname} if $disabled->{$tname};
+ $marked_as_disabled= 1;
+ $tinfo->{'comment'}= $disabled->{$tname};
}
if ( -f $disabled_file )
{
- $tinfo->{'skip'}= 1;
- $tinfo->{'disable'}= 1; # Sub type of 'skip'
+ $marked_as_disabled= 1;
$tinfo->{'comment'}= mtr_fromfile($disabled_file);
}
+ # If test was marked as disabled, either opt_enable_disabled is off and then
+ # we skip this test, or it is on and then we run this test but warn
+
+ if ( $marked_as_disabled )
+ {
+ if ( $::opt_enable_disabled )
+ {
+ $tinfo->{'dont_skip_though_disabled'}= 1;
+ }
+ else
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'disable'}= 1; # Sub type of 'skip'
+ return;
+ }
+ }
+
+ if ( $component_id eq 'im' )
+ {
+ if ( $::glob_use_embedded_server )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No IM with embedded server";
+ return;
+ }
+ elsif ( $::opt_ps_protocol )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No IM with --ps-protocol";
+ return;
+ }
+ elsif ( $::opt_skip_im )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No IM tests(--skip-im)";
+ return;
+ }
+ }
+ else
+ {
+ mtr_options_from_test_file($tinfo,"$testdir/${tname}.test");
+
+ if ( $tinfo->{'big_test'} and ! $::opt_big_test )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need 'big-test' option";
+ return;
+ }
+
+ if ( $tinfo->{'ndb_extra'} and ! $::opt_ndb_extra_test )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need 'ndb_extra' option";
+ return;
+ }
+
+ if ( $tinfo->{'require_manager'} )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need the _old_ manager(to be removed)";
+ return;
+ }
+
+ if ( defined $tinfo->{'binlog_format'} and
+ ! ( $tinfo->{'binlog_format'} eq $::used_binlog_format ) )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Not running with binlog format '$tinfo->{'binlog_format'}'";
+ return;
+ }
+
+ if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need debug binaries";
+ return;
+ }
+ }
+
# We can't restart a running server that may be in use
if ( $::glob_use_running_server and
( $tinfo->{'master_restart'} or $tinfo->{'slave_restart'} ) )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Can't restart a running server";
+ return;
}
+
}
+# List of tags in the .test files that if found should set
+# the specified value in "tinfo"
+our @tags=
+(
+ ["include/have_innodb.inc", "innodb_test", 1],
+ ["include/have_binlog_format_row.inc", "binlog_format", "row"],
+ ["include/have_binlog_format_statement.inc", "binlog_format", "stmt"],
+ ["include/big_test.inc", "big_test", 1],
+ ["include/have_debug.inc", "need_debug", 1],
+ ["include/have_ndb_extra.inc", "ndb_extra", 1],
+ ["require_manager", "require_manager", 1],
+);
+
+sub mtr_options_from_test_file($$) {
+ my $tinfo= shift;
+ my $file= shift;
+ #mtr_verbose("$file");
+ my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!");
+
+ while ( my $line= <$F> )
+ {
+ next if ( $line !~ /^--/ );
+
+ # Match this line against tag in "tags" array
+ foreach my $tag (@tags)
+ {
+ if ( index($line, $tag->[0]) >= 0 )
+ {
+ # Tag matched, assign value to "tinfo"
+ $tinfo->{"$tag->[1]"}= $tag->[2];
+ }
+ }
+
+ # If test sources another file, open it as well
+ if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ )
+ {
+ my $value= $2;
+ $value =~ s/^\s+//; # Remove leading space
+ $value =~ s/[[:space:]]+$//; # Remove ending space
+
+ my $sourced_file= "$::glob_mysql_test_dir/$value";
+ mtr_options_from_test_file($tinfo, $sourced_file);
+ }
+
+ }
+}
+
1;
diff --git a/mysql-test/lib/mtr_im.pl b/mysql-test/lib/mtr_im.pl
new file mode 100644
index 00000000000..ca17516278e
--- /dev/null
+++ b/mysql-test/lib/mtr_im.pl
@@ -0,0 +1,761 @@
+# -*- cperl -*-
+
+# This is a library file used by the Perl version of mysql-test-run,
+# and is part of the translation of the Bourne shell script with the
+# same name.
+
+use strict;
+
+# Private IM-related operations.
+
+sub mtr_im_kill_process ($$$$);
+sub mtr_im_load_pids ($);
+sub mtr_im_terminate ($);
+sub mtr_im_check_alive ($);
+sub mtr_im_check_main_alive ($);
+sub mtr_im_check_angel_alive ($);
+sub mtr_im_check_mysqlds_alive ($);
+sub mtr_im_check_mysqld_alive ($);
+sub mtr_im_cleanup ($);
+sub mtr_im_rm_file ($);
+sub mtr_im_errlog ($);
+sub mtr_im_kill ($);
+sub mtr_im_wait_for_connection ($$$);
+sub mtr_im_wait_for_mysqld($$$);
+
+# Public IM-related operations.
+
+sub mtr_im_start ($$);
+sub mtr_im_stop ($);
+
+##############################################################################
+#
+# Private operations.
+#
+##############################################################################
+
+sub mtr_im_kill_process ($$$$) {
+ my $pid_lst= shift;
+ my $signal= shift;
+ my $total_retries= shift;
+ my $timeout= shift;
+
+ my %pids;
+
+ foreach my $pid ( @{$pid_lst} )
+ {
+ $pids{$pid}= 1;
+ }
+
+ for ( my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt )
+ {
+ foreach my $pid ( keys %pids )
+ {
+ mtr_debug("Sending $signal to $pid...");
+
+ kill($signal, $pid);
+
+ unless ( kill (0, $pid) )
+ {
+ mtr_debug("Process $pid died.");
+ delete $pids{$pid};
+ }
+ }
+
+ return if scalar keys %pids == 0;
+
+ mtr_debug("Sleeping $timeout second(s) waiting for processes to die...");
+
+ sleep($timeout);
+ }
+
+ mtr_debug("Process(es) " .
+ join(' ', keys %pids) .
+ " is still alive after $total_retries " .
+ "of sending signal $signal.");
+}
+
+###########################################################################
+
+sub mtr_im_load_pids($) {
+ my $im= shift;
+
+ mtr_debug("Loading PID files...");
+
+ # Obtain mysqld-process pids.
+
+ my $instances = $im->{'instances'};
+
+ for ( my $idx= 0; $idx < 2; ++$idx )
+ {
+ mtr_debug("IM-guarded mysqld[$idx] PID file: '" .
+ $instances->[$idx]->{'path_pid'} . "'.");
+
+ my $mysqld_pid;
+
+ if ( -r $instances->[$idx]->{'path_pid'} )
+ {
+ $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'});
+ mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid.");
+ }
+ else
+ {
+ $mysqld_pid= undef;
+ mtr_debug("IM-guarded mysqld[$idx]: no PID file.");
+ }
+
+ $instances->[$idx]->{'pid'}= $mysqld_pid;
+ }
+
+ # Re-read Instance Manager PIDs from the file, since during tests Instance
+ # Manager could have been restarted, so its PIDs could have been changed.
+
+ # - IM-main
+
+ mtr_debug("IM-main PID file: '$im->{path_pid}'.");
+
+ if ( -f $im->{'path_pid'} )
+ {
+ $im->{'pid'} =
+ mtr_get_pid_from_file($im->{'path_pid'});
+
+ mtr_debug("IM-main PID: $im->{pid}.");
+ }
+ else
+ {
+ mtr_debug("IM-main: no PID file.");
+ $im->{'pid'}= undef;
+ }
+
+ # - IM-angel
+
+ mtr_debug("IM-angel PID file: '$im->{path_angel_pid}'.");
+
+ if ( -f $im->{'path_angel_pid'} )
+ {
+ $im->{'angel_pid'} =
+ mtr_get_pid_from_file($im->{'path_angel_pid'});
+
+ mtr_debug("IM-angel PID: $im->{'angel_pid'}.");
+ }
+ else
+ {
+ mtr_debug("IM-angel: no PID file.");
+ $im->{'angel_pid'} = undef;
+ }
+}
+
+###########################################################################
+
+sub mtr_im_terminate($) {
+ my $im= shift;
+
+ # Load pids from pid-files. We should do it first of all, because IM deletes
+ # them on shutdown.
+
+ mtr_im_load_pids($im);
+
+ mtr_debug("Shutting Instance Manager down...");
+
+ # Ignoring SIGCHLD so that all children could rest in peace.
+
+ start_reap_all();
+
+ # Send SIGTERM to IM-main.
+
+ if ( defined $im->{'pid'} )
+ {
+ mtr_debug("IM-main pid: $im->{pid}.");
+ mtr_debug("Stopping IM-main...");
+
+ mtr_im_kill_process([ $im->{'pid'} ], 'TERM', 10, 1);
+ }
+ else
+ {
+ mtr_debug("IM-main pid: n/a.");
+ }
+
+ # If IM-angel was alive, wait for it to die.
+
+ if ( defined $im->{'angel_pid'} )
+ {
+ mtr_debug("IM-angel pid: $im->{'angel_pid'}.");
+ mtr_debug("Waiting for IM-angel to die...");
+
+ my $total_attempts= 10;
+
+ for ( my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt )
+ {
+ unless ( kill (0, $im->{'angel_pid'}) )
+ {
+ mtr_debug("IM-angel died.");
+ last;
+ }
+
+ sleep(1);
+ }
+ }
+ else
+ {
+ mtr_debug("IM-angel pid: n/a.");
+ }
+
+ stop_reap_all();
+
+ # Re-load PIDs.
+
+ mtr_im_load_pids($im);
+}
+
+###########################################################################
+
+sub mtr_im_check_alive($) {
+ my $im= shift;
+
+ mtr_debug("Checking whether IM-components are alive...");
+
+ return 1 if mtr_im_check_main_alive($im);
+
+ return 1 if mtr_im_check_angel_alive($im);
+
+ return 1 if mtr_im_check_mysqlds_alive($im);
+
+ return 0;
+}
+
+###########################################################################
+
+sub mtr_im_check_main_alive($) {
+ my $im= shift;
+
+ # Check that the process, that we know to be IM's, is dead.
+
+ if ( defined $im->{'pid'} )
+ {
+ if ( kill (0, $im->{'pid'}) )
+ {
+ mtr_debug("IM-main (PID: $im->{pid}) is alive.");
+ return 1;
+ }
+ else
+ {
+ mtr_debug("IM-main (PID: $im->{pid}) is dead.");
+ }
+ }
+ else
+ {
+ mtr_debug("No PID file for IM-main.");
+ }
+
+ # Check that IM does not accept client connections.
+
+ if ( mtr_ping_port($im->{'port'}) )
+ {
+ mtr_debug("IM-main (port: $im->{port}) " .
+ "is accepting connections.");
+
+ mtr_im_errlog("IM-main is accepting connections on port " .
+ "$im->{port}, but there is no " .
+ "process information.");
+ return 1;
+ }
+ else
+ {
+ mtr_debug("IM-main (port: $im->{port}) " .
+ "does not accept connections.");
+ return 0;
+ }
+}
+
+###########################################################################
+
+sub mtr_im_check_angel_alive($) {
+ my $im= shift;
+
+ # Check that the process, that we know to be the Angel, is dead.
+
+ if ( defined $im->{'angel_pid'} )
+ {
+ if ( kill (0, $im->{'angel_pid'}) )
+ {
+ mtr_debug("IM-angel (PID: $im->{angel_pid}) is alive.");
+ return 1;
+ }
+ else
+ {
+ mtr_debug("IM-angel (PID: $im->{angel_pid}) is dead.");
+ return 0;
+ }
+ }
+ else
+ {
+ mtr_debug("No PID file for IM-angel.");
+ return 0;
+ }
+}
+
+###########################################################################
+
+sub mtr_im_check_mysqlds_alive($) {
+ my $im= shift;
+
+ mtr_debug("Checking for IM-guarded mysqld instances...");
+
+ my $instances = $im->{'instances'};
+
+ for ( my $idx= 0; $idx < 2; ++$idx )
+ {
+ mtr_debug("Checking mysqld[$idx]...");
+
+ return 1
+ if mtr_im_check_mysqld_alive($instances->[$idx]);
+ }
+}
+
+###########################################################################
+
+sub mtr_im_check_mysqld_alive($) {
+ my $mysqld_instance= shift;
+
+ # Check that the process is dead.
+
+ if ( defined $mysqld_instance->{'pid'} )
+ {
+ if ( kill (0, $mysqld_instance->{'pid'}) )
+ {
+ mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive.");
+ return 1;
+ }
+ else
+ {
+ mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead.");
+ }
+ }
+ else
+ {
+ mtr_debug("No PID file for mysqld instance.");
+ }
+
+ # Check that mysqld does not accept client connections.
+
+ if ( mtr_ping_port($mysqld_instance->{'port'}) )
+ {
+ mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " .
+ "is accepting connections.");
+
+ mtr_im_errlog("Mysqld is accepting connections on port " .
+ "$mysqld_instance->{port}, but there is no " .
+ "process information.");
+ return 1;
+ }
+ else
+ {
+ mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " .
+ "does not accept connections.");
+ return 0;
+ }
+}
+
+###########################################################################
+
+sub mtr_im_cleanup($) {
+ my $im= shift;
+
+ mtr_im_rm_file($im->{'path_pid'});
+ mtr_im_rm_file($im->{'path_sock'});
+
+ mtr_im_rm_file($im->{'path_angel_pid'});
+
+ for ( my $idx= 0; $idx < 2; ++$idx )
+ {
+ mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_pid'});
+ mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_sock'});
+ }
+}
+
+###########################################################################
+
+sub mtr_im_rm_file($)
+{
+ my $file_path= shift;
+
+ if ( -f $file_path )
+ {
+ mtr_debug("Removing '$file_path'...");
+
+ unless ( unlink($file_path) )
+ {
+ mtr_warning("Can not remove '$file_path'.")
+ }
+ }
+ else
+ {
+ mtr_debug("File '$file_path' does not exist already.");
+ }
+}
+
+###########################################################################
+
+sub mtr_im_errlog($) {
+ my $msg= shift;
+
+ # Complain in error log so that a warning will be shown.
+ #
+ # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so
+ # that it can be seen on console and does not produce pushbuild error.
+
+ # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err";
+ #
+ # open (ERRLOG, ">>$errlog") ||
+ # mtr_error("Can not open error log ($errlog)");
+ #
+ # my $ts= localtime();
+ # print ERRLOG
+ # "Warning: [$ts] $msg\n";
+ #
+ # close ERRLOG;
+
+ my $ts= localtime();
+ print "Warning: [$ts] $msg\n";
+}
+
+###########################################################################
+
+sub mtr_im_kill($) {
+ my $im= shift;
+
+ # Re-load PIDs. That can be useful because some processes could have been
+ # restarted.
+
+ mtr_im_load_pids($im);
+
+ # Ignoring SIGCHLD so that all children could rest in peace.
+
+ start_reap_all();
+
+ # Kill IM-angel first of all.
+
+ if ( defined $im->{'angel_pid'} )
+ {
+ mtr_debug("Killing IM-angel (PID: $im->{angel_pid})...");
+ mtr_im_kill_process([ $im->{'angel_pid'} ], 'KILL', 10, 1)
+ }
+ else
+ {
+ mtr_debug("IM-angel is dead.");
+ }
+
+ # Re-load PIDs again.
+
+ mtr_im_load_pids($im);
+
+ # Kill IM-main.
+
+ if ( defined $im->{'pid'} )
+ {
+ mtr_debug("Killing IM-main (PID: $im->pid})...");
+ mtr_im_kill_process([ $im->{'pid'} ], 'KILL', 10, 1);
+ }
+ else
+ {
+ mtr_debug("IM-main is dead.");
+ }
+
+ # Re-load PIDs again.
+
+ mtr_im_load_pids($im);
+
+ # Kill guarded mysqld instances.
+
+ my @mysqld_pids;
+
+ mtr_debug("Collecting PIDs of mysqld instances to kill...");
+
+ for ( my $idx= 0; $idx < 2; ++$idx )
+ {
+ my $pid= $im->{'instances'}->[$idx]->{'pid'};
+
+ unless ( defined $pid )
+ {
+ next;
+ }
+
+ mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid.");
+
+ push (@mysqld_pids, $pid);
+ }
+
+ if ( scalar @mysqld_pids > 0 )
+ {
+ mtr_debug("Killing IM-guarded mysqld instances...");
+ mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1);
+ }
+
+ # That's all.
+
+ stop_reap_all();
+}
+
+##############################################################################
+
+sub mtr_im_wait_for_connection($$$) {
+ my $im= shift;
+ my $total_attempts= shift;
+ my $connect_timeout= shift;
+
+ mtr_debug("Waiting for IM on port $im->{port} " .
+ "to start accepting connections...");
+
+ for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt )
+ {
+ mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)...");
+
+ if ( mtr_ping_port($im->{'port'}) )
+ {
+ mtr_debug("IM is accepting connections " .
+ "on port $im->{port}.");
+ return 1;
+ }
+
+ mtr_debug("Sleeping $connect_timeout...");
+ sleep($connect_timeout);
+ }
+
+ mtr_debug("IM does not accept connections " .
+ "on port $im->{port} after " .
+ ($total_attempts * $connect_timeout) . " seconds.");
+
+ return 0;
+}
+
+##############################################################################
+
+sub mtr_im_wait_for_mysqld($$$) {
+ my $mysqld= shift;
+ my $total_attempts= shift;
+ my $connect_timeout= shift;
+
+ mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " .
+ "to start accepting connections...");
+
+ for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt )
+ {
+ mtr_debug("Trying to connect to mysqld " .
+ "($cur_attempt of $total_attempts)...");
+
+ if ( mtr_ping_port($mysqld->{'port'}) )
+ {
+ mtr_debug("Mysqld is accepting connections " .
+ "on port $mysqld->{port}.");
+ return 1;
+ }
+
+ mtr_debug("Sleeping $connect_timeout...");
+ sleep($connect_timeout);
+ }
+
+ mtr_debug("Mysqld does not accept connections " .
+ "on port $mysqld->{port} after " .
+ ($total_attempts * $connect_timeout) . " seconds.");
+
+ return 0;
+}
+
+##############################################################################
+#
+# Public operations.
+#
+##############################################################################
+
+sub mtr_im_start($$) {
+ my $im = shift;
+ my $opts = shift;
+
+ mtr_debug("Starting Instance Manager...");
+
+ my $args;
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--defaults-file=%s", $im->{'defaults_file'});
+
+ foreach my $opt ( @{$opts} )
+ {
+ mtr_add_arg($args, $opt);
+ }
+
+ $im->{'pid'} =
+ mtr_spawn(
+ $::exe_im, # path to the executable
+ $args, # cmd-line args
+ '', # stdin
+ $im->{'path_log'}, # stdout
+ $im->{'path_err'}, # stderr
+ '', # pid file path (not used)
+ { append_log_file => 1 } # append log files
+ );
+
+ unless ( $im->{'pid'} )
+ {
+ mtr_error('Could not start Instance Manager.')
+ }
+
+ # Instance Manager can be run in daemon mode. In this case, it creates
+ # several processes and the parent process, created by mtr_spawn(), exits just
+ # after start. So, we have to obtain Instance Manager PID from the PID file.
+
+ mtr_debug("Waiting for IM to create PID file (" .
+ "path: '$im->{path_pid}'; " .
+ "timeout: $im->{start_timeout})...");
+
+ unless ( sleep_until_file_created($im->{'path_pid'},
+ $im->{'start_timeout'},
+ -1) ) # real PID is still unknown
+ {
+ mtr_debug("IM has not created PID file in $im->{start_timeout} secs.");
+ mtr_debug("Aborting test suite...");
+
+ mtr_kill_leftovers();
+
+ mtr_report("IM has not created PID file in $im->{start_timeout} secs.");
+ return 0;
+ }
+
+ $im->{'pid'}= mtr_get_pid_from_file($im->{'path_pid'});
+
+ mtr_debug("Instance Manager started. PID: $im->{pid}.");
+
+ # Wait until we can connect to IM.
+
+ my $IM_CONNECT_TIMEOUT= 30;
+
+ unless ( mtr_im_wait_for_connection($im,
+ $IM_CONNECT_TIMEOUT, 1) )
+ {
+ mtr_debug("Can not connect to Instance Manager " .
+ "in $IM_CONNECT_TIMEOUT seconds after start.");
+ mtr_debug("Aborting test suite...");
+
+ mtr_kill_leftovers();
+
+ mtr_report("Can not connect to Instance Manager " .
+ "in $IM_CONNECT_TIMEOUT seconds after start.");
+ return 0;
+ }
+
+ # Wait for IM to start guarded instances:
+ # - wait for PID files;
+
+ mtr_debug("Waiting for guarded mysqlds instances to create PID files...");
+
+ for ( my $idx= 0; $idx < 2; ++$idx )
+ {
+ my $mysqld= $im->{'instances'}->[$idx];
+
+ if ( exists $mysqld->{'nonguarded'} )
+ {
+ next;
+ }
+
+ mtr_debug("Waiting for mysqld[$idx] to create PID file (" .
+ "path: '$mysqld->{path_pid}'; " .
+ "timeout: $mysqld->{start_timeout})...");
+
+ unless ( sleep_until_file_created($mysqld->{'path_pid'},
+ $mysqld->{'start_timeout'},
+ -1) ) # real PID is still unknown
+ {
+ mtr_debug("mysqld[$idx] has not created PID file in " .
+ "$mysqld->{start_timeout} secs.");
+ mtr_debug("Aborting test suite...");
+
+ mtr_kill_leftovers();
+
+ mtr_report("mysqld[$idx] has not created PID file in " .
+ "$mysqld->{start_timeout} secs.");
+ return 0;
+ }
+
+ mtr_debug("PID file for mysqld[$idx] ($mysqld->{path_pid} created.");
+ }
+
+ # Wait until we can connect to guarded mysqld-instances
+ # (in other words -- wait for IM to start guarded instances).
+
+ mtr_debug("Waiting for guarded mysqlds to start accepting connections...");
+
+ for ( my $idx= 0; $idx < 2; ++$idx )
+ {
+ my $mysqld= $im->{'instances'}->[$idx];
+
+ if ( exists $mysqld->{'nonguarded'} )
+ {
+ next;
+ }
+
+ mtr_debug("Waiting for mysqld[$idx] to accept connection...");
+
+ unless ( mtr_im_wait_for_mysqld($mysqld, 30, 1) )
+ {
+ mtr_debug("Can not connect to mysqld[$idx] " .
+ "in $IM_CONNECT_TIMEOUT seconds after start.");
+ mtr_debug("Aborting test suite...");
+
+ mtr_kill_leftovers();
+
+ mtr_report("Can not connect to mysqld[$idx] " .
+ "in $IM_CONNECT_TIMEOUT seconds after start.");
+ return 0;
+ }
+
+ mtr_debug("mysqld[$idx] started.");
+ }
+
+ mtr_debug("Instance Manager and its components are up and running.");
+
+ return 1;
+}
+
+##############################################################################
+
+sub mtr_im_stop($) {
+ my $im= shift;
+
+ mtr_debug("Stopping Instance Manager...");
+
+ # Try graceful shutdown.
+
+ mtr_im_terminate($im);
+
+ # Check that all processes died.
+
+ unless ( mtr_im_check_alive($im) )
+ {
+ mtr_debug("Instance Manager has been stopped successfully.");
+ mtr_im_cleanup($im);
+ return 1;
+ }
+
+ # Instance Manager don't want to die. We should kill it.
+
+ mtr_im_errlog("Instance Manager did not shutdown gracefully.");
+
+ mtr_im_kill($im);
+
+ # Check again that all IM-related processes have been killed.
+
+ my $im_is_alive= mtr_im_check_alive($im);
+
+ mtr_im_cleanup($im);
+
+ if ( $im_is_alive )
+ {
+ mtr_debug("Can not kill Instance Manager or its children.");
+ return 0;
+ }
+
+ mtr_debug("Instance Manager has been killed successfully.");
+ return 1;
+}
+
+###########################################################################
+
+1;
diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl
index b3da6d97664..8a7fc56269c 100644
--- a/mysql-test/lib/mtr_io.pl
+++ b/mysql-test/lib/mtr_io.pl
@@ -11,6 +11,8 @@ sub mtr_get_opts_from_file ($);
sub mtr_fromfile ($);
sub mtr_tofile ($@);
sub mtr_tonewfile($@);
+sub mtr_lastlinefromfile($);
+sub mtr_appendfile_to_file ($$);
##############################################################################
#
@@ -19,13 +21,39 @@ sub mtr_tonewfile($@);
##############################################################################
sub mtr_get_pid_from_file ($) {
- my $file= shift;
+ my $pid_file_path= shift;
+ my $TOTAL_ATTEMPTS= 30;
+ my $timeout= 1;
- open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!");
- my $pid= <FILE>;
- chomp($pid);
- close FILE;
- return $pid;
+ # We should read from the file until we get correct pid. As it is
+ # stated in BUG#21884, pid file can be empty at some moment. So, we should
+ # read it until we get valid data.
+
+ for (my $cur_attempt= 1; $cur_attempt <= $TOTAL_ATTEMPTS; ++$cur_attempt)
+ {
+ mtr_debug("Reading pid file '$pid_file_path' " .
+ "($cur_attempt of $TOTAL_ATTEMPTS)...");
+
+ open(FILE, '<', $pid_file_path)
+ or mtr_error("can't open file \"$pid_file_path\": $!");
+
+ my $pid= <FILE>;
+
+ chomp($pid) if defined $pid;
+
+ close FILE;
+
+ return $pid if defined $pid && $pid ne '';
+
+ mtr_debug("Pid file '$pid_file_path' is empty. " .
+ "Sleeping $timeout second(s)...");
+
+ sleep(1);
+ }
+
+ mtr_error("Pid file '$pid_file_path' is corrupted. " .
+ "Can not retrieve PID in " .
+ ($timeout * $TOTAL_ATTEMPTS) . " seconds.");
}
sub mtr_get_opts_from_file ($) {
@@ -113,6 +141,20 @@ sub mtr_fromfile ($) {
return $text;
}
+sub mtr_lastlinefromfile ($) {
+ my $file= shift;
+ my $text;
+
+ open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!");
+ while (my $line= <FILE>)
+ {
+ $text= $line;
+ }
+ close FILE;
+ return $text;
+}
+
+
sub mtr_tofile ($@) {
my $file= shift;
@@ -129,5 +171,17 @@ sub mtr_tonewfile ($@) {
close FILE;
}
+sub mtr_appendfile_to_file ($$) {
+ my $from_file= shift;
+ my $to_file= shift;
+
+ open(TOFILE,">>",$to_file) or mtr_error("can't open file \"$to_file\": $!");
+ open(FROMFILE,">>",$from_file)
+ or mtr_error("can't open file \"$from_file\": $!");
+ print TOFILE while (<FROMFILE>);
+ close FROMFILE;
+ close TOFILE;
+}
+
1;
diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl
index 08c99e90906..dd9d24ebc8e 100644
--- a/mysql-test/lib/mtr_misc.pl
+++ b/mysql-test/lib/mtr_misc.pl
@@ -9,9 +9,10 @@ use strict;
sub mtr_full_hostname ();
sub mtr_short_hostname ();
sub mtr_init_args ($);
-sub mtr_add_arg ($$);
+sub mtr_add_arg ($$@);
sub mtr_path_exists(@);
sub mtr_script_exists(@);
+sub mtr_file_exists(@);
sub mtr_exe_exists(@);
sub mtr_copy_dir($$);
sub mtr_same_opts($$);
@@ -54,7 +55,7 @@ sub mtr_init_args ($) {
$$args = []; # Empty list
}
-sub mtr_add_arg ($$) {
+sub mtr_add_arg ($$@) {
my $args= shift;
my $format= shift;
my @fargs = @_;
@@ -101,6 +102,14 @@ sub mtr_script_exists (@) {
}
}
+sub mtr_file_exists (@) {
+ foreach my $path ( @_ )
+ {
+ return $path if -e $path;
+ }
+ return "";
+}
+
sub mtr_exe_exists (@) {
my @path= @_;
map {$_.= ".exe"} @path if $::glob_win32;
@@ -125,19 +134,30 @@ sub mtr_exe_exists (@) {
}
}
+
sub mtr_copy_dir($$) {
- my $srcdir= shift;
- my $dstdir= shift;
+ my $from_dir= shift;
+ my $to_dir= shift;
- # Create destination directory
- mkpath($dstdir);
- find(\&mtr_copy_one_file, $dstdir);
-}
+# mtr_verbose("Copying from $from_dir to $to_dir");
+
+ mkpath("$to_dir");
+ opendir(DIR, "$from_dir")
+ or mtr_error("Can't find $from_dir$!");
+ for(readdir(DIR)) {
+ next if "$_" eq "." or "$_" eq "..";
+ if ( -d "$from_dir/$_" )
+ {
+ mtr_copy_dir("$from_dir/$_", "$to_dir/$_");
+ next;
+ }
+ copy("$from_dir/$_", "$to_dir/$_");
+ }
+ closedir(DIR);
-sub mtr_copy_one_file {
- print $File::Find::name, "\n";
}
+
sub mtr_same_opts ($$) {
my $l1= shift;
my $l2= shift;
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 662b70a4fee..5e21248790e 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -4,7 +4,6 @@
# and is part of the translation of the Bourne shell script with the
# same name.
-#use Carp qw(cluck);
use Socket;
use Errno;
use strict;
@@ -14,12 +13,17 @@ use POSIX 'WNOHANG';
sub mtr_run ($$$$$$;$);
sub mtr_spawn ($$$$$$;$);
-sub mtr_stop_mysqld_servers ($);
+sub mtr_check_stop_servers ($);
sub mtr_kill_leftovers ();
+sub mtr_wait_blocking ($);
sub mtr_record_dead_children ();
+sub mtr_ndbmgm_start($$);
+sub mtr_mysqladmin_start($$$);
sub mtr_exit ($);
sub sleep_until_file_created ($$$);
sub mtr_kill_processes ($);
+sub mtr_ping_with_timeout($);
+sub mtr_ping_port ($);
# static in C
sub spawn_impl ($$$$$$$$);
@@ -31,7 +35,6 @@ sub spawn_impl ($$$$$$$$);
##############################################################################
# This function try to mimic the C version used in "netware/mysql_test_run.c"
-# FIXME learn it to handle append mode as well, a "new" flag or a "append"
sub mtr_run ($$$$$$;$) {
my $path= shift;
@@ -112,6 +115,9 @@ sub spawn_impl ($$$$$$$$) {
print STDERR "#### ", "-" x 78, "\n";
}
+ mtr_error("Can't spawn with empty \"path\"") unless defined $path;
+
+
FORK:
{
my $pid= fork();
@@ -144,17 +150,6 @@ sub spawn_impl ($$$$$$$$) {
$SIG{INT}= 'DEFAULT'; # Parent do some stuff, we don't
- if ( $::glob_cygwin_shell and $mode eq 'test' )
- {
- # Programs started from mysqltest under Cygwin, are to
- # execute them within Cygwin. Else simple things in test
- # files like
- # --system "echo 1 > file"
- # will fail.
- # FIXME not working :-(
-# $ENV{'COMSPEC'}= "$::glob_cygwin_shell -c";
- }
-
my $log_file_open_mode = '>';
if ($spawn_opts and $spawn_opts->{'append_log_file'})
@@ -164,7 +159,15 @@ sub spawn_impl ($$$$$$$$) {
if ( $output )
{
- if ( ! open(STDOUT,$log_file_open_mode,$output) )
+ if ( $::glob_win32_perl )
+ {
+ # Don't redirect stdout on ActiveState perl since this is
+ # just another thread in the same process.
+ # Should be fixed so that the thread that is created with fork
+ # executes the exe in another process and wait's for it to return.
+ # In the meanwhile, we get all the output from mysqld's to screen
+ }
+ elsif ( ! open(STDOUT,$log_file_open_mode,$output) )
{
mtr_child_error("can't redirect STDOUT to \"$output\": $!");
}
@@ -216,8 +219,7 @@ sub spawn_parent_impl {
{
# Simple run of command, we wait for it to return
my $ret_pid= waitpid($pid,0);
-
- if ( $ret_pid <= 0 )
+ if ( $ret_pid != $pid )
{
mtr_error("$path ($pid) got lost somehow");
}
@@ -245,7 +247,6 @@ sub spawn_parent_impl {
# Someone terminated, don't know who. Collect
# status info first before $? is lost,
# but not $exit_value, this is flagged from
- #
my $timer_name= mtr_timer_timeout($::glob_timers, $ret_pid);
if ( $timer_name )
@@ -272,45 +273,22 @@ sub spawn_parent_impl {
last;
}
- # If one of the mysqld processes died, we want to
- # mark this, and kill the mysqltest process.
-
- foreach my $idx (0..1)
- {
- if ( $::master->[$idx]->{'pid'} eq $ret_pid )
- {
- mtr_debug("child $ret_pid was master[$idx], " .
- "exit during mysqltest run");
- $::master->[$idx]->{'pid'}= 0;
- last;
- }
- }
-
- foreach my $idx (0..2)
- {
- if ( $::slave->[$idx]->{'pid'} eq $ret_pid )
- {
- mtr_debug("child $ret_pid was slave[$idx], " .
- "exit during mysqltest run");
- $::slave->[$idx]->{'pid'}= 0;
- last;
- }
- }
+ # One of the child processes died, unless this was expected
+ # mysqltest should be killed and test aborted
- mtr_debug("waitpid() catched exit of unknown child $ret_pid, " .
- "exit during mysqltest run");
+ check_expected_crash_and_restart($ret_pid);
}
if ( $ret_pid != $pid )
{
# We terminated the waiting because a "mysqld" process died.
# Kill the mysqltest process.
-
+ mtr_verbose("Kill mysqltest because another process died");
kill(9,$pid);
$ret_pid= waitpid($pid,0);
- if ( $ret_pid == -1 )
+ if ( $ret_pid != $pid )
{
mtr_error("$path ($pid) got lost somehow");
}
@@ -351,39 +329,101 @@ sub mtr_process_exit_status {
#
##############################################################################
-# We just "ping" on the ports, and if we can't do a socket connect
-# we assume the server is dead. So we don't *really* know a server
-# is dead, we just hope that it after letting the listen port go,
-# it is dead enough for us to start a new server.
+# Kill all processes(mysqld, ndbd, ndb_mgmd and im) that would conflict with
+# this run
+# Make sure to remove the PID file, if any.
+# kill IM manager first, else it will restart the servers
sub mtr_kill_leftovers () {
- # First, kill all masters and slaves that would conflict with
- # this run. Make sure to remove the PID file, if any.
+ mtr_report("Killing Possible Leftover Processes");
+ mtr_debug("mtr_kill_leftovers(): started.");
- my @args;
+ mkpath("$::opt_vardir/log"); # Needed for mysqladmin log
- for ( my $idx; $idx < 2; $idx++ )
+ # Stop or kill Instance Manager and all its children. If we failed to do
+ # that, we can only abort -- there is nothing left to do.
+
+# mtr_error("Failed to stop Instance Manager.")
+# unless mtr_im_stop($::instance_manager);
+
+ # Start shutdown of masters and slaves. Don't touch IM-managed mysqld
+ # instances -- they should be stopped by mtr_im_stop().
+
+ mtr_debug("Shutting down mysqld-instances...");
+
+ my @kill_pids;
+ my %admin_pids;
+
+ foreach my $srv (@{$::master}, @{$::slave})
{
- push(@args,{
- pid => 0, # We don't know the PID
- pidfile => $::master->[$idx]->{'path_mypid'},
- sockfile => $::master->[$idx]->{'path_mysock'},
- port => $::master->[$idx]->{'path_myport'},
- });
+ mtr_debug(" - mysqld " .
+ "(pid: $srv->{pid}; " .
+ "pid file: '$srv->{path_pid}'; " .
+ "socket: '$srv->{path_sock}'; ".
+ "port: $srv->{port})");
+
+ my $pid= mtr_mysqladmin_start($srv, "shutdown", 70);
+
+ # Save the pid of the mysqladmin process
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $srv->{'pid'},
+ pidfile => $srv->{'path_pid'},
+ sockfile => $srv->{'path_sock'},
+ port => $srv->{'port'},
+ });
+ $srv->{'pid'}= 0; # Assume we are done with it
}
- for ( my $idx; $idx < 3; $idx++ )
+ if ( ! $::opt_skip_ndbcluster )
{
- push(@args,{
- pid => 0, # We don't know the PID
- pidfile => $::slave->[$idx]->{'path_mypid'},
- sockfile => $::slave->[$idx]->{'path_mysock'},
- port => $::slave->[$idx]->{'path_myport'},
- });
+ # Start shutdown of clusters.
+ mtr_debug("Shutting down cluster...");
+
+ foreach my $cluster (@{$::clusters})
+ {
+ mtr_debug(" - cluster " .
+ "(pid: $cluster->{pid}; " .
+ "pid file: '$cluster->{path_pid})");
+
+ my $pid= mtr_ndbmgm_start($cluster, "shutdown");
+
+ # Save the pid of the ndb_mgm process
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ mtr_debug(" - ndbd " .
+ "(pid: $ndbd->{pid}; " .
+ "pid file: '$ndbd->{path_pid})");
+
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0; # Assume we are done with it
+ }
+ }
}
- mtr_mysqladmin_shutdown(\@args, 20);
+ # Wait for all the admin processes to complete
+ mtr_wait_blocking(\%admin_pids);
+
+ # If we trusted "mysqladmin --shutdown_timeout= ..." we could just
+ # terminate now, but we don't (FIXME should be debugged).
+ # So we try again to ping and at least wait the same amount of time
+ # mysqladmin would for all to die.
+
+ mtr_ping_with_timeout(\@kill_pids);
# We now have tried to terminate nice. We have waited for the listen
# port to be free, but can't really tell if the mysqld process died
@@ -401,6 +441,8 @@ sub mtr_kill_leftovers () {
# FIXME $path_run_dir or something
my $rundir= "$::opt_vardir/run";
+ mtr_debug("Processing PID files in directory '$rundir'...");
+
if ( -d $rundir )
{
opendir(RUNDIR, $rundir)
@@ -414,26 +456,32 @@ sub mtr_kill_leftovers () {
if ( -f $pidfile )
{
- my $pid= mtr_get_pid_from_file($pidfile);
+ mtr_debug("Processing PID file: '$pidfile'...");
- # Race, could have been removed between I tested with -f
- # and the unlink() below, so I better check again with -f
+ my $pid= mtr_get_pid_from_file($pidfile);
- if ( ! unlink($pidfile) and -f $pidfile )
- {
- mtr_error("can't remove $pidfile");
- }
+ mtr_debug("Got pid: $pid from file '$pidfile'");
if ( $::glob_cygwin_perl or kill(0, $pid) )
{
+ mtr_debug("There is process with pid $pid -- scheduling for kill.");
push(@pids, $pid); # We know (cygwin guess) it exists
}
+ else
+ {
+ mtr_debug("There is no process with pid $pid -- skipping.");
+ }
}
}
closedir(RUNDIR);
if ( @pids )
{
+ mtr_debug("Killing the following processes with PID files: " .
+ join(' ', @pids) . "...");
+
+ start_reap_all();
+
if ( $::glob_cygwin_perl )
{
# We have no (easy) way of knowing the Cygwin controlling
@@ -447,8 +495,9 @@ sub mtr_kill_leftovers () {
my $retries= 10; # 10 seconds
do
{
+ mtr_debug("Sending SIGKILL to pids: " . join(' ', @pids));
kill(9, @pids);
- mtr_debug("Sleep 1 second waiting for processes to die");
+ mtr_report("Sleep 1 second waiting for processes to die");
sleep(1) # Wait one second
} while ( $retries-- and kill(0, @pids) );
@@ -457,56 +506,74 @@ sub mtr_kill_leftovers () {
mtr_warning("can't kill process(es) " . join(" ", @pids));
}
}
+
+ stop_reap_all();
}
}
+ else
+ {
+ mtr_debug("Directory for PID files ($rundir) does not exist.");
+ }
- # We may have failed everything, bug we now check again if we have
+ # We may have failed everything, but we now check again if we have
# the listen ports free to use, and if they are free, just go for it.
- foreach my $srv ( @args )
+ mtr_debug("Checking known mysqld servers...");
+
+ foreach my $srv ( @kill_pids )
{
- if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) )
+ if ( defined $srv->{'port'} and mtr_ping_port($srv->{'port'}) )
{
- mtr_warning("can't kill old mysqld holding port $srv->{'port'}");
+ mtr_warning("can't kill old process holding port $srv->{'port'}");
}
}
-}
-##############################################################################
-#
-# Shut down mysqld servers we have started from this run of this script
-#
-##############################################################################
+ mtr_debug("mtr_kill_leftovers(): finished.");
+}
-# To speed things we kill servers in parallel. The argument is a list
-# of 'ports', 'pids', 'pidfiles' and 'socketfiles'.
+# Check that all processes in list are killed
+# The argument is a list of 'ports', 'pids', 'pidfiles' and 'socketfiles'
+# for which shutdown has been started. Make sure they all get killed
+# in one way or the other.
+#
# FIXME On Cygwin, and maybe some other platforms, $srv->{'pid'} and
-# $srv->{'pidfile'} will not be the same PID. We need to try to kill
+# the pid in $srv->{'pidfile'} will not be the same PID. We need to try to kill
# both I think.
-sub mtr_stop_mysqld_servers ($) {
+sub mtr_check_stop_servers ($) {
my $spec= shift;
- # ----------------------------------------------------------------------
- # First try nice normal shutdown using 'mysqladmin'
- # ----------------------------------------------------------------------
+ # Return if no processes are defined
+ return if ! @$spec;
- # Shutdown time must be high as slave may be in reconnect
- mtr_mysqladmin_shutdown($spec, 70);
+ #mtr_report("mtr_check_stop_servers");
+
+ mtr_ping_with_timeout(\@$spec);
# ----------------------------------------------------------------------
# We loop with waitpid() nonblocking to see how many of the ones we
- # are to kill, actually got killed by mtr_mysqladmin_shutdown().
- # Note that we don't rely on this, the mysqld server might have stop
+ # are to kill, actually got killed by mysqladmin or ndb_mgm
+ #
+ # Note that we don't rely on this, the mysqld server might have stopped
# listening to the port, but still be alive. But it is a start.
# ----------------------------------------------------------------------
foreach my $srv ( @$spec )
{
- if ( $srv->{'pid'} and (waitpid($srv->{'pid'},&WNOHANG) == $srv->{'pid'}) )
+ my $ret_pid;
+ if ( $srv->{'pid'} )
{
- $srv->{'pid'}= 0;
+ $ret_pid= waitpid($srv->{'pid'},&WNOHANG);
+ if ($ret_pid == $srv->{'pid'})
+ {
+ mtr_verbose("Caught exit of process $ret_pid");
+ $srv->{'pid'}= 0;
+ }
+ else
+ {
+ # mtr_warning("caught exit of unknown child $ret_pid");
+ }
}
}
@@ -540,13 +607,12 @@ sub mtr_stop_mysqld_servers ($) {
}
# ----------------------------------------------------------------------
- # If the processes where started from this script, and we had no PIDS
+ # If all the processes in list already have been killed,
# then we don't have to do anything.
# ----------------------------------------------------------------------
if ( ! keys %mysqld_pids )
{
- # cluck "This is how we got here!";
return;
}
@@ -595,139 +661,288 @@ sub mtr_stop_mysqld_servers ($) {
foreach my $file ($srv->{'pidfile'}, $srv->{'sockfile'})
{
# Know it is dead so should be no race, careful anyway
- if ( -f $file and ! unlink($file) and -f $file )
+ if ( defined $file and -f $file and ! unlink($file) and -f $file )
{
$errors++;
mtr_warning("couldn't delete $file");
}
}
+ $srv->{'pid'}= 0;
}
}
}
if ( $errors )
{
- # We are in trouble, just die....
- mtr_error("we could not kill or clean up all processes");
+ # There where errors killing processes
+ # do one last attempt to ping the servers
+ # and if they can't be pinged, assume they are dead
+ if ( ! mtr_ping_with_timeout( \@$spec ) )
+ {
+ mtr_error("we could not kill or clean up all processes");
+ }
+ else
+ {
+ mtr_verbose("All ports were free, continuing");
+ }
}
}
# FIXME We just assume they are all dead, for Cygwin we are not
# really sure
-
+
}
+# Wait for all the process in the list to terminate
+sub mtr_wait_blocking($) {
+ my $admin_pids= shift;
-##############################################################################
-#
-# Shut down mysqld servers using "mysqladmin ... shutdown".
-# To speed this up, we start them in parallel and use waitpid() to
-# catch their termination. Note that this doesn't say the servers
-# are terminated, just that 'mysqladmin' is terminated.
-#
-# Note that mysqladmin will ask the server about what PID file it uses,
-# and mysqladmin will wait for it to be removed before it terminates
-# (unless passes timeout).
-#
-# This function will take at most about 20 seconds, and we still are not
-# sure we killed them all. If none is responding to ping, we return 1,
-# else we return 0.
-#
-##############################################################################
-sub mtr_mysqladmin_shutdown {
- my $spec= shift;
+ # Return if no processes defined
+ return if ! %$admin_pids;
+
+ mtr_verbose("mtr_wait_blocking");
+
+ # Wait for all the started processes to exit
+ # As mysqladmin is such a simple program, we trust it to terminate itself.
+ # I.e. we wait blocking, and wait for them all before we go on.
+ foreach my $pid (keys %{$admin_pids})
+ {
+ my $ret_pid= waitpid($pid,0);
+
+ }
+}
+
+# Start "mysqladmin shutdown" for a specific mysqld
+sub mtr_mysqladmin_start($$$) {
+ my $srv= shift;
+ my $command= shift;
my $adm_shutdown_tmo= shift;
- my %mysql_admin_pids;
- my @to_kill_specs;
+ my $args;
+ mtr_init_args(\$args);
- foreach my $srv ( @$spec )
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--user=%s", $::opt_user);
+ mtr_add_arg($args, "--password=");
+ mtr_add_arg($args, "--silent");
+ if ( -e $srv->{'path_sock'} )
+ {
+ mtr_add_arg($args, "--socket=%s", $srv->{'path_sock'});
+ }
+ if ( $srv->{'port'} )
{
- if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) )
+ mtr_add_arg($args, "--port=%s", $srv->{'port'});
+ }
+ if ( $srv->{'port'} and ! -e $srv->{'path_sock'} )
+ {
+ mtr_add_arg($args, "--protocol=tcp"); # Needed if no --socket
+ }
+ mtr_add_arg($args, "--connect_timeout=5");
+
+ # Shutdown time must be high as slave may be in reconnect
+ mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo");
+ mtr_add_arg($args, "$command");
+ my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log";
+ my $pid= mtr_spawn($::exe_mysqladmin, $args,
+ "", $path_mysqladmin_log, $path_mysqladmin_log, "",
+ { append_log_file => 1 });
+ mtr_verbose("mtr_mysqladmin_start, pid: $pid");
+ return $pid;
+
+}
+
+# Start "ndb_mgm shutdown" for a specific cluster, it will
+# shutdown all data nodes and leave the ndb_mgmd running
+sub mtr_ndbmgm_start($$) {
+ my $cluster= shift;
+ my $command= shift;
+
+ my $args;
+
+ mtr_init_args(\$args);
+
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--try-reconnect=1");
+ mtr_add_arg($args, "--ndb_connectstring=%s", $cluster->{'connect_string'});
+ mtr_add_arg($args, "-e");
+ mtr_add_arg($args, "$command");
+
+ my $pid= mtr_spawn($::exe_ndb_mgm, $args,
+ "", "/dev/null", "/dev/null", "",
+ {});
+ mtr_verbose("mtr_ndbmgm_start, pid: $pid");
+ return $pid;
+
+}
+
+
+# Ping all servers in list, exit when none of them answers
+# or when timeout has passed
+sub mtr_ping_with_timeout($) {
+ my $spec= shift;
+ my $timeout= 200; # 20 seconds max
+ my $res= 1; # If we just fall through, we are done
+ # in the sense that the servers don't
+ # listen to their ports any longer
+
+ mtr_debug("Waiting for mysqld servers to stop...");
+
+ TIME:
+ while ( $timeout-- )
+ {
+ foreach my $srv ( @$spec )
{
- push(@to_kill_specs, $srv);
+ $res= 1; # We are optimistic
+ if ( $srv->{'pid'} and defined $srv->{'port'} )
+ {
+ if ( mtr_ping_port($srv->{'port'}) )
+ {
+ mtr_verbose("waiting for process $srv->{'pid'} to stop ".
+ "using port $srv->{'port'}");
+
+ # Millisceond sleep emulated with select
+ select(undef, undef, undef, (0.1));
+ $res= 0;
+ next TIME;
+ }
+ else
+ {
+ # Process was not using port
+ }
+ }
}
+ last; # If we got here, we are done
}
-
- foreach my $srv ( @to_kill_specs )
+ if ($res)
+ {
+ mtr_debug("mtr_ping_with_timeout(): All mysqld instances are down.");
+ }
+ else
{
- # FIXME wrong log.....
- # FIXME, stderr.....
- # Shutdown time must be high as slave may be in reconnect
- my $args;
+ mtr_report("mtr_ping_with_timeout(): At least one server is alive.");
+ }
- mtr_init_args(\$args);
+ return $res;
+}
+
+
+#
+# Loop through our list of processes and look for and entry
+# with the provided pid
+# Set the pid of that process to 0 if found
+#
+sub mark_process_dead($)
+{
+ my $ret_pid= shift;
- mtr_add_arg($args, "--no-defaults");
- mtr_add_arg($args, "--user=%s", $::opt_user);
- mtr_add_arg($args, "--password=");
- if ( -e $srv->{'sockfile'} )
+ foreach my $mysqld (@{$::master}, @{$::slave})
+ {
+ if ( $mysqld->{'pid'} eq $ret_pid )
{
- mtr_add_arg($args, "--socket=%s", $srv->{'sockfile'});
+ mtr_verbose("$mysqld->{'type'} $mysqld->{'idx'} exited, pid: $ret_pid");
+ $mysqld->{'pid'}= 0;
+ return;
}
- if ( $srv->{'port'} )
+ }
+
+ foreach my $cluster (@{$::clusters})
+ {
+ if ( $cluster->{'pid'} eq $ret_pid )
{
- mtr_add_arg($args, "--port=%s", $srv->{'port'});
+ mtr_verbose("$cluster->{'name'} cluster ndb_mgmd exited, pid: $ret_pid");
+ $cluster->{'pid'}= 0;
+ return;
}
- if ( $srv->{'port'} and ! -e $srv->{'sockfile'} )
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
{
- mtr_add_arg($args, "--protocol=tcp"); # Needed if no --socket
+ if ( $ndbd->{'pid'} eq $ret_pid )
+ {
+ mtr_verbose("$cluster->{'name'} cluster ndbd exited, pid: $ret_pid");
+ $ndbd->{'pid'}= 0;
+ return;
+ }
}
- mtr_add_arg($args, "--connect_timeout=5");
- mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo");
- mtr_add_arg($args, "shutdown");
- # We don't wait for termination of mysqladmin
- my $pid= mtr_spawn($::exe_mysqladmin, $args,
- "", $::path_manager_log, $::path_manager_log, "",
- { append_log_file => 1 });
- $mysql_admin_pids{$pid}= 1;
}
+ mtr_warning("mark_process_dead couldn't find an entry for pid: $ret_pid");
+
+}
+
+#
+# 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.
+#
+sub check_expected_crash_and_restart($)
+{
+ my $ret_pid= shift;
- # As mysqladmin is such a simple program, we trust it to terminate.
- # I.e. we wait blocking, and wait wait for them all before we go on.
- while (keys %mysql_admin_pids)
+ foreach my $mysqld (@{$::master}, @{$::slave})
{
- foreach my $pid (keys %mysql_admin_pids)
+ if ( $mysqld->{'pid'} eq $ret_pid )
{
- if ( waitpid($pid,0) > 0 )
+ mtr_verbose("$mysqld->{'type'} $mysqld->{'idx'} exited, pid: $ret_pid");
+ $mysqld->{'pid'}= 0;
+
+ # Check if crash expected and restart if it was
+ my $expect_file= "$::opt_vardir/tmp/" . "$mysqld->{'type'}" .
+ "$mysqld->{'idx'}" . ".expect";
+ if ( -f $expect_file )
{
- delete $mysql_admin_pids{$pid};
+ mtr_verbose("Crash was expected, file $expect_file exists");
+ mysqld_start($mysqld, $mysqld->{'start_opts'},
+ $mysqld->{'start_slave_master_info'});
+ unlink($expect_file);
}
+
+ return;
}
}
- # If we trusted "mysqladmin --shutdown_timeout= ..." we could just
- # terminate now, but we don't (FIXME should be debugged).
- # So we try again to ping and at least wait the same amount of time
- # mysqladmin would for all to die.
-
- my $timeout= 20; # 20 seconds max
- my $res= 1; # If we just fall through, we are done
- # in the sense that the servers don't
- # listen to their ports any longer
- TIME:
- while ( $timeout-- )
+ foreach my $cluster (@{$::clusters})
{
- foreach my $srv ( @to_kill_specs )
+ if ( $cluster->{'pid'} eq $ret_pid )
{
- $res= 1; # We are optimistic
- if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) )
+ mtr_verbose("$cluster->{'name'} cluster ndb_mgmd exited, pid: $ret_pid");
+ $cluster->{'pid'}= 0;
+
+ # Check if crash expected and restart if it was
+ my $expect_file= "$::opt_vardir/tmp/ndb_mgmd_" . "$cluster->{'type'}" .
+ ".expect";
+ if ( -f $expect_file )
{
- mtr_debug("Sleep 1 second waiting for processes to stop using port");
- sleep(1); # One second
- $res= 0;
- next TIME;
+ mtr_verbose("Crash was expected, file $expect_file exists");
+ ndbmgmd_start($cluster);
+ unlink($expect_file);
}
+ return;
}
- last; # If we got here, we are done
- }
-
- $timeout or mtr_debug("At least one server is still listening to its port");
- sleep(5) if $::glob_win32; # FIXME next startup fails if no sleep
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ if ( $ndbd->{'pid'} eq $ret_pid )
+ {
+ mtr_verbose("$cluster->{'name'} cluster ndbd exited, pid: $ret_pid");
+ $ndbd->{'pid'}= 0;
+
+ # Check if crash expected and restart if it was
+ my $expect_file= "$::opt_vardir/tmp/ndbd_" . "$cluster->{'type'}" .
+ "$ndbd->{'idx'}" . ".expect";
+ if ( -f $expect_file )
+ {
+ mtr_verbose("Crash was expected, file $expect_file exists");
+ ndbd_start($cluster, $ndbd->{'idx'},
+ $ndbd->{'start_extra_args'});
+ unlink($expect_file);
+ }
+ return;
+ }
+ }
+ }
+ mtr_warning("check_expected_crash_and_restart couldn't find an entry for pid: $ret_pid");
- return $res;
}
##############################################################################
@@ -740,32 +955,18 @@ sub mtr_mysqladmin_shutdown {
sub mtr_record_dead_children () {
+ my $process_died= 0;
my $ret_pid;
- # FIXME the man page says to wait for -1 to terminate,
- # but on OS X we get '0' all the time...
- while ( ($ret_pid= waitpid(-1,&WNOHANG)) > 0 )
+ # Wait without blockinng to see if any processes had died
+ # -1 or 0 means there are no more procesess to wait for
+ while ( ($ret_pid= waitpid(-1,&WNOHANG)) != 0 and $ret_pid != -1)
{
- mtr_debug("waitpid() catched exit of child $ret_pid");
- foreach my $idx (0..1)
- {
- if ( $::master->[$idx]->{'pid'} eq $ret_pid )
- {
- mtr_debug("child $ret_pid was master[$idx]");
- $::master->[$idx]->{'pid'}= 0;
- }
- }
-
- foreach my $idx (0..2)
- {
- if ( $::slave->[$idx]->{'pid'} eq $ret_pid )
- {
- mtr_debug("child $ret_pid was slave[$idx]");
- $::slave->[$idx]->{'pid'}= 0;
- last;
- }
- }
+ mtr_warning("mtr_record_dead_children: $ret_pid");
+ mark_process_dead($ret_pid);
+ $process_died= 1;
}
+ return $process_died;
}
sub start_reap_all {
@@ -777,16 +978,24 @@ sub start_reap_all {
# here. If a process terminated before setting $SIG{CHLD} (but after
# any attempt to waitpid() it), it will still be a zombie. So we
# have to handle any such process here.
- while(waitpid(-1, &WNOHANG) > 0) { };
+ my $pid;
+ while(($pid= waitpid(-1, &WNOHANG)) != 0 and $pid != -1)
+ {
+ mtr_warning("start_reap_all pid: $pid");
+ mark_process_dead($pid);
+ };
}
sub stop_reap_all {
$SIG{CHLD}= 'DEFAULT';
}
-sub mtr_ping_mysqld_server () {
+
+sub mtr_ping_port ($) {
my $port= shift;
+ mtr_verbose("mtr_ping_port: $port");
+
my $remote= "localhost";
my $iaddr= inet_aton($remote);
if ( ! $iaddr )
@@ -799,13 +1008,18 @@ sub mtr_ping_mysqld_server () {
{
mtr_error("can't create socket: $!");
}
+
+ mtr_debug("Pinging server (port: $port)...");
+
if ( connect(SOCK, $paddr) )
{
close(SOCK); # FIXME check error?
+ mtr_verbose("USED");
return 1;
}
else
{
+ mtr_verbose("FREE");
return 0;
}
}
@@ -822,30 +1036,36 @@ sub sleep_until_file_created ($$$) {
my $pidfile= shift;
my $timeout= shift;
my $pid= shift;
+ my $sleeptime= 100; # Milliseconds
+ my $loops= ($timeout * 1000) / $sleeptime;
- for ( my $loop= 1; $loop <= $timeout; $loop++ )
+ for ( my $loop= 1; $loop <= $loops; $loop++ )
{
if ( -r $pidfile )
{
return $pid;
}
- # Check if it died after the fork() was successful
- if ( waitpid($pid,&WNOHANG) == $pid )
+ # Check if it died after the fork() was successful
+ if ( $pid != 0 && waitpid($pid,&WNOHANG) == $pid )
{
+ mtr_warning("Process $pid died");
return 0;
}
- mtr_debug("Sleep 1 second waiting for creation of $pidfile");
+ mtr_debug("Sleep $sleeptime milliseconds waiting for $pidfile");
- if ( $loop % 60 == 0 )
+ # Print extra message every 60 seconds
+ my $seconds= ($loop * $sleeptime) / 1000;
+ if ( $seconds > 1 and int($seconds) % 60 == 0 )
{
- my $left= $timeout - $loop;
- mtr_warning("Waited $loop seconds for $pidfile to be created, " .
+ my $left= $timeout - $seconds;
+ mtr_warning("Waited $seconds seconds for $pidfile to be created, " .
"still waiting for $left seconds...");
}
- sleep(1);
+ # Millisceond sleep emulated with select
+ select(undef, undef, undef, ($sleeptime/1000));
}
return 0;
@@ -855,18 +1075,18 @@ sub sleep_until_file_created ($$$) {
sub mtr_kill_processes ($) {
my $pids = shift;
- foreach my $sig (15,9)
+ mtr_verbose("mtr_kill_processes " . join(" ", @$pids));
+
+ foreach my $pid (@$pids)
{
- my $retries= 20; # FIXME 20 seconds, this is silly!
- kill($sig, @{$pids});
- while ( $retries-- and kill(0, @{$pids}) )
+ foreach my $sig (15, 9)
{
- mtr_debug("Sleep 1 second waiting for processes to die");
- sleep(1) # Wait one second
+ last if mtr_im_kill_process([ $pid ], $sig, 10, 1);
}
}
}
+
##############################################################################
#
# When we exit, we kill off all children
@@ -876,7 +1096,7 @@ sub mtr_kill_processes ($) {
# FIXME something is wrong, we sometimes terminate with "Hangup" written
# to tty, and no STDERR output telling us why.
-# FIXME for some readon, setting HUP to 'IGNORE' will cause exit() to
+# FIXME for some reason, setting HUP to 'IGNORE' will cause exit() to
# write out "Hangup", and maybe loose some output. We insert a sleep...
sub mtr_exit ($) {
@@ -884,9 +1104,18 @@ sub mtr_exit ($) {
# cluck("Called mtr_exit()");
mtr_timer_stop_all($::glob_timers);
local $SIG{HUP} = 'IGNORE';
- kill('HUP', -$$);
- sleep 2;
+ # ToDo: Signalling -$$ will only work if we are the process group
+ # leader (in fact on QNX it will signal our session group leader,
+ # which might be Do-compile or Pushbuild, causing tests to be
+ # aborted). So we only do it if we are the group leader. We might
+ # set ourselves as the group leader at startup (with
+ # POSIX::setpgrp(0,0)), but then care must be needed to always do
+ # proper child process cleanup.
+ kill('HUP', -$$) if !$::glob_win32_perl and $$ == getpgrp();
+
exit($code);
}
+###########################################################################
+
1;
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index 515988ee5c7..6e3796133f2 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -10,6 +10,7 @@ sub mtr_report_test_name($);
sub mtr_report_test_passed($);
sub mtr_report_test_failed($);
sub mtr_report_test_skipped($);
+sub mtr_report_test_not_skipped_though_disabled($);
sub mtr_show_failed_diff ($);
sub mtr_report_stats ($);
@@ -21,6 +22,7 @@ sub mtr_warning (@);
sub mtr_error (@);
sub mtr_child_error (@);
sub mtr_debug (@);
+sub mtr_verbose (@);
##############################################################################
@@ -36,6 +38,7 @@ sub mtr_show_failed_diff ($) {
my $reject_file= "r/$tname.reject";
my $result_file= "r/$tname.result";
+ my $log_file= "r/$tname.log";
my $eval_file= "r/$tname.eval";
if ( $::opt_suite ne "main" )
@@ -43,10 +46,11 @@ sub mtr_show_failed_diff ($) {
$reject_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$reject_file";
$result_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$result_file";
$eval_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$eval_file";
+ $log_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$log_file";
}
if ( -f $eval_file )
- {
+ {
$result_file= $eval_file;
}
elsif ( $::opt_result_ext and
@@ -70,6 +74,12 @@ sub mtr_show_failed_diff ($) {
print "http://www.mysql.com/doc/en/Reporting_mysqltest_bugs.html\n";
print "to find the reason to this problem and how to report this.\n\n";
}
+
+ if ( -f $log_file )
+ {
+ print "Result from queries before failure can be found in $log_file\n";
+ # FIXME Maybe a tail -f -n 10 $log_file here
+ }
}
sub mtr_report_test_name ($) {
@@ -88,7 +98,24 @@ sub mtr_report_test_skipped ($) {
}
else
{
- print "[ skipped ]\n";
+ print "[ skipped ] $tinfo->{'comment'}\n";
+ }
+}
+
+sub mtr_report_tests_not_skipped_though_disabled ($) {
+ my $tests= shift;
+
+ if ( $::opt_enable_disabled )
+ {
+ my @disabled_tests= grep {$_->{'dont_skip_though_disabled'}} @$tests;
+ if ( @disabled_tests )
+ {
+ print "\nTest(s) which will be run though they are marked as disabled:\n";
+ foreach my $tinfo ( sort {$a->{'name'} cmp $b->{'name'}} @disabled_tests )
+ {
+ printf " %-20s : %s\n", $tinfo->{'name'}, $tinfo->{'comment'};
+ }
+ }
}
}
@@ -99,7 +126,7 @@ sub mtr_report_test_passed ($) {
if ( $::opt_timer and -f "$::opt_vardir/log/timer" )
{
$timer= mtr_fromfile("$::opt_vardir/log/timer");
- $::glob_tot_real_time += $timer;
+ $::glob_tot_real_time += ($timer/1000);
$timer= sprintf "%12s", $timer;
}
$tinfo->{'result'}= 'MTR_RES_PASSED';
@@ -114,6 +141,11 @@ sub mtr_report_test_failed ($) {
{
print "[ fail ] timeout\n";
}
+ elsif ( $tinfo->{'ndb_test'} and $::cluster->[0]->{'installed_ok'} eq "NO")
+ {
+ print "[ fail ] ndbcluster start failure\n";
+ return;
+ }
else
{
print "[ fail ]\n";
@@ -144,6 +176,8 @@ sub mtr_report_stats ($) {
my $tot_passed= 0;
my $tot_failed= 0;
my $tot_tests= 0;
+ my $tot_restarts= 0;
+ my $found_problems= 0; # Some warnings are errors...
foreach my $tinfo (@$tests)
{
@@ -161,6 +195,10 @@ sub mtr_report_stats ($) {
$tot_tests++;
$tot_failed++;
}
+ if ( $tinfo->{'restarted'} )
+ {
+ $tot_restarts++;
+ }
}
# ----------------------------------------------------------------------
@@ -183,41 +221,69 @@ sub mtr_report_stats ($) {
"the documentation at\n",
"http://www.mysql.com/doc/en/MySQL_test_suite.html\n";
}
+ print
+ "The servers were restarted $tot_restarts times\n";
+
+ if ( $::opt_timer )
+ {
+ print
+ "Spent $::glob_tot_real_time seconds actually executing testcases\n"
+ }
# ----------------------------------------------------------------------
+ # If a debug run, there might be interesting information inside
+ # the "var/log/*.err" files. We save this info in "var/log/warnings"
# ----------------------------------------------------------------------
if ( ! $::glob_use_running_server )
{
+ # Save and report if there was any fatal warnings/errors in err logs
- # Report if there was any fatal warnings/errors in the log files
- #
- unlink("$::opt_vardir/log/warnings");
- unlink("$::opt_vardir/log/warnings.tmp");
- # Remove some non fatal warnings from the log files
-
-# FIXME what is going on ????? ;-)
-# sed -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \
-# var/log/*.err \
-# | sed -e 's!Warning: Table:.* on rename!!g' \
-# > var/log/warnings.tmp;
-#
-# found_error=0;
-# # Find errors
-# for i in "^Warning:" "^Error:" "^==.* at 0x"
-# do
-# if ( $GREP "$i" var/log/warnings.tmp >> var/log/warnings )
-# {
-# found_error=1
-# }
-# done
-# unlink("$::opt_vardir/log/warnings.tmp");
-# if ( $found_error= "1" )
-# {
-# print "WARNING: Got errors/warnings while running tests. Please examine\n"
-# print "$::opt_vardir/log/warnings for details.\n"
-# }
-# }
+ my $warnlog= "$::opt_vardir/log/warnings";
+
+ unless ( open(WARN, ">$warnlog") )
+ {
+ mtr_warning("can't write to the file \"$warnlog\": $!");
+ }
+ else
+ {
+ # We report different types of problems in order
+ foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x",
+ "InnoDB: Warning", "missing DBUG_RETURN",
+ "mysqld: Warning",
+ "Attempting backtrace", "Assertion .* failed" )
+ {
+ foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") )
+ {
+ unless ( open(ERR, $errlog) )
+ {
+ mtr_warning("can't read $errlog");
+ next;
+ }
+ while ( <ERR> )
+ {
+ # Skip some non fatal warnings from the log files
+ if ( /Warning:\s+Table:.* on (delete|rename)/ or
+ /Warning:\s+Setting lower_case_table_names=2/ or
+ /Warning:\s+One can only use the --user.*root/ or
+ /InnoDB: Warning: we did not need to do crash recovery/)
+ {
+ next; # Skip these lines
+ }
+ if ( /$pattern/ )
+ {
+ $found_problems= 1;
+ print WARN $_;
+ }
+ }
+ }
+ }
+ if ( $found_problems )
+ {
+ mtr_warning("Got errors/warnings while running tests, please examine",
+ "\"$warnlog\" for details.");
+ }
+ }
}
print "\n";
@@ -235,6 +301,9 @@ sub mtr_report_stats ($) {
}
}
print "\n";
+ }
+ if ( $tot_failed != 0 || $found_problems)
+ {
mtr_error("there where failing test cases");
}
}
@@ -298,5 +367,11 @@ sub mtr_debug (@) {
print STDERR "####: ",join(" ", @_),"\n";
}
}
+sub mtr_verbose (@) {
+ if ( $::opt_verbose )
+ {
+ print STDERR "> ",join(" ", @_),"\n";
+ }
+}
1;
diff --git a/mysql-test/lib/mtr_stress.pl b/mysql-test/lib/mtr_stress.pl
new file mode 100644
index 00000000000..a7d4b68b69d
--- /dev/null
+++ b/mysql-test/lib/mtr_stress.pl
@@ -0,0 +1,178 @@
+# -*- cperl -*-
+
+# This is a library file used by the Perl version of mysql-test-run,
+# and is part of the translation of the Bourne shell script with the
+# same name.
+
+use strict;
+use File::Spec;
+
+# These are not to be prefixed with "mtr_"
+
+sub run_stress_test ();
+
+##############################################################################
+#
+# Run tests in the stress mode
+#
+##############################################################################
+
+sub run_stress_test ()
+{
+
+ my $args;
+ my $stress_suitedir;
+
+ mtr_report("Starting stress testing\n");
+
+ if ( ! $::glob_use_embedded_server )
+ {
+ if ( ! mysqld_start($::master->[0],[],[]) )
+ {
+ mtr_error("Can't start the mysqld server");
+ }
+ }
+
+ my $stress_basedir=File::Spec->catdir($::opt_vardir, "stress");
+
+ #Clean up stress dir
+ if ( -d $stress_basedir )
+ {
+ rmtree($stress_basedir);
+ }
+ mkpath($stress_basedir);
+
+ if ($::opt_stress_suite ne 'main' && $::opt_stress_suite ne 'default' )
+ {
+ $stress_suitedir=File::Spec->catdir($::glob_mysql_test_dir, "suite",
+ $::opt_stress_suite);
+ }
+ else
+ {
+ $stress_suitedir=$::glob_mysql_test_dir;
+ }
+
+ if ( -d $stress_suitedir )
+ {
+ #$stress_suite_t_dir=File::Spec->catdir($stress_suitedir, "t");
+ #$stress_suite_r_dir=File::Spec->catdir($stress_suitedir, "r");
+ #FIXME: check dirs above for existence to ensure that test suite
+ # contains tests and results dirs
+ }
+ else
+ {
+ mtr_error("Specified test suite $::opt_stress_suite doesn't exist");
+ }
+
+ if ( @::opt_cases )
+ {
+ $::opt_stress_test_file=File::Spec->catfile($stress_basedir, "stress_tests.txt");
+ open(STRESS_FILE, ">$::opt_stress_test_file");
+ print STRESS_FILE join("\n",@::opt_cases),"\n";
+ close(STRESS_FILE);
+ }
+ elsif ( $::opt_stress_test_file )
+ {
+ $::opt_stress_test_file=File::Spec->catfile($stress_suitedir,
+ $::opt_stress_test_file);
+ if ( ! -f $::opt_stress_test_file )
+ {
+ mtr_error("Specified file $::opt_stress_test_file with list of tests does not exist\n",
+ "Please ensure that file exists and has proper permissions");
+ }
+ }
+ else
+ {
+ $::opt_stress_test_file=File::Spec->catfile($stress_suitedir,
+ "stress_tests.txt");
+ if ( ! -f $::opt_stress_test_file )
+ {
+ mtr_error("Default file $::opt_stress_test_file with list of tests does not exist\n",
+ "Please use --stress-test-file option to specify custom one or you can\n",
+ "just specify name of test for testing as last argument in command line");
+
+ }
+ }
+
+ if ( $::opt_stress_init_file )
+ {
+ $::opt_stress_init_file=File::Spec->catfile($stress_suitedir,
+ $::opt_stress_init_file);
+ if ( ! -f $::opt_stress_init_file )
+ {
+ mtr_error("Specified file $::opt_stress_init_file with list of tests does not exist\n",
+ "Please ensure that file exists and has proper permissions");
+ }
+ }
+ else
+ {
+ $::opt_stress_init_file=File::Spec->catfile($stress_suitedir,
+ "stress_init.txt");
+ if ( ! -f $::opt_stress_init_file )
+ {
+ $::opt_stress_init_file='';
+ }
+ }
+
+ if ( $::opt_stress_mode ne 'random' && $::opt_stress_mode ne 'seq' )
+ {
+ mtr_error("You specified wrong mode $::opt_stress_mode for stress test\n",
+ "Correct values are 'random' or 'seq'");
+ }
+
+ mtr_init_args(\$args);
+
+ mtr_add_arg($args, "--server-socket=%s", $::master->[0]->{'path_mysock'});
+ mtr_add_arg($args, "--server-user=%s", $::opt_user);
+ mtr_add_arg($args, "--server-database=%s", "test");
+ mtr_add_arg($args, "--stress-suite-basedir=%s", $::glob_mysql_test_dir);
+ mtr_add_arg($args, "--suite=%s", $::opt_stress_suite);
+ mtr_add_arg($args, "--stress-tests-file=%s", $::opt_stress_test_file);
+ mtr_add_arg($args, "--stress-basedir=%s", $stress_basedir);
+ mtr_add_arg($args, "--server-logs-dir=%s", $stress_basedir);
+ mtr_add_arg($args, "--stress-mode=%s", $::opt_stress_mode);
+ mtr_add_arg($args, "--mysqltest=%s", $::exe_mysqltest);
+ mtr_add_arg($args, "--threads=%s", $::opt_stress_threads);
+ mtr_add_arg($args, "--verbose");
+ mtr_add_arg($args, "--cleanup");
+ mtr_add_arg($args, "--log-error-details");
+ mtr_add_arg($args, "--abort-on-error");
+
+ if ( $::opt_stress_init_file )
+ {
+ mtr_add_arg($args, "--stress-init-file=%", $::opt_stress_init_file);
+ }
+
+ if ( !$::opt_stress_loop_count && !$::opt_stress_test_count &&
+ !$::opt_stress_test_duration )
+ {
+ #Limit stress testing with 20 loops in case when any limit parameter
+ #was specified
+ $::opt_stress_test_count=20;
+ }
+
+ if ( $::opt_stress_loop_count )
+ {
+ mtr_add_arg($args, "--loop-count=%s", $::opt_stress_loop_count);
+ }
+
+ if ( $::opt_stress_test_count )
+ {
+ mtr_add_arg($args, "--test-count=%s", $::opt_stress_test_count);
+ }
+
+ if ( $::opt_stress_test_duration )
+ {
+ mtr_add_arg($args, "--test-duration=%s", $::opt_stress_test_duration);
+ }
+
+ #Run stress test
+ mtr_run("$::glob_mysql_test_dir/mysql-stress-test.pl", $args, "", "", "", "");
+
+ if ( ! $::glob_use_embedded_server )
+ {
+ stop_masters();
+ }
+}
+
+1;
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index d1e049ff883..39c116a3fcb 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -66,10 +66,6 @@
# "http://www.plover.com/~mjd/perl/Trace/" and run this script like
# "perl -d:Trace mysql-test-run.pl"
#
-# FIXME Save a PID file from this code as well, to record the process
-# id we think it has. In Cygwin, a fork creates one Cygwin process,
-# and then the real Win32 process. Cygwin Perl can only kill Cygwin
-# processes. And "mysqld --bootstrap ..." doesn't save a PID file.
$Devel::Trace::TRACE= 0; # Don't trace boring init stuff
@@ -80,14 +76,19 @@ use File::Copy;
use Cwd;
use Getopt::Long;
use Sys::Hostname;
-#use Carp;
use IO::Socket;
use IO::Socket::INET;
use Data::Dumper;
use strict;
#use diagnostics;
+our $glob_win32_perl= ($^O eq "MSWin32"); # ActiveState Win32 Perl
+our $glob_cygwin_perl= ($^O eq "cygwin"); # Cygwin Perl
+our $glob_win32= ($glob_win32_perl or $glob_cygwin_perl);
+our $glob_netware= ($^O eq "NetWare"); # NetWare
+
require "lib/mtr_cases.pl";
+require "lib/mtr_im.pl";
require "lib/mtr_process.pl";
require "lib/mtr_timer.pl";
require "lib/mtr_io.pl";
@@ -97,6 +98,7 @@ require "lib/mtr_report.pl";
require "lib/mtr_diff.pl";
require "lib/mtr_match.pl";
require "lib/mtr_misc.pl";
+require "lib/mtr_stress.pl";
$Devel::Trace::TRACE= 1;
@@ -128,11 +130,7 @@ our @mysqld_src_dirs=
# structs. We let each struct be a separate hash.
# Misc global variables
-
-our $glob_win32= 0; # OS and native Win32 executables
-our $glob_win32_perl= 0; # ActiveState Win32 Perl
-our $glob_cygwin_perl= 0; # Cygwin Perl
-our $glob_cygwin_shell= undef;
+our $mysql_version_id;
our $glob_mysql_test_dir= undef;
our $glob_mysql_bench_dir= undef;
our $glob_hostname= undef;
@@ -140,32 +138,30 @@ our $glob_scriptname= undef;
our $glob_timers= undef;
our $glob_use_running_server= 0;
our $glob_use_running_ndbcluster= 0;
+our $glob_use_running_ndbcluster_slave= 0;
our $glob_use_embedded_server= 0;
our @glob_test_mode;
our $glob_basedir;
-# The total result
-
our $path_charsetsdir;
our $path_client_bindir;
our $path_language;
our $path_timefile;
-our $path_manager_log; # Used by mysqldadmin
-our $path_slave_load_tmpdir; # What is this?!
+our $path_snapshot;
our $path_mysqltest_log;
+our $path_current_test_log;
our $path_my_basedir;
+
our $opt_vardir; # A path but set directly on cmd line
+our $path_vardir_trace; # unix formatted opt_vardir for trace files
our $opt_tmpdir; # A path but set directly on cmd line
our $opt_usage;
our $opt_suite;
-our $opt_netware;
-
our $opt_script_debug= 0; # Script debugging, enable with --script-debug
-
-# Options FIXME not all....
+our $opt_verbose= 0; # Verbose output, enable with --verbose
our $exe_master_mysqld;
our $exe_mysql;
@@ -173,13 +169,21 @@ our $exe_mysqladmin;
our $exe_mysqlbinlog;
our $exe_mysql_client_test;
our $exe_mysqld;
-our $exe_mysqldump; # Called from test case
-our $exe_mysqlimport; # Called from test case
-our $exe_mysqlshow; # Called from test case
+our $exe_mysqlcheck;
+our $exe_mysqldump;
+our $exe_mysqlslap;
+our $exe_mysqlimport;
+our $exe_mysqlshow;
our $exe_mysql_fix_system_tables;
our $exe_mysqltest;
+our $exe_ndbd;
+our $exe_ndb_mgmd;
our $exe_slave_mysqld;
+our $exe_im;
our $exe_my_print_defaults;
+our $exe_perror;
+our $lib_udf_example;
+our $exe_libtool;
our $opt_bench= 0;
our $opt_small_bench= 0;
@@ -187,10 +191,15 @@ our $opt_big_test= 0; # Send --big-test to mysqltest
our @opt_extra_mysqld_opt;
-our $opt_comment;
our $opt_compress;
-our $opt_current_test;
-our $opt_ddd;
+our $opt_ssl;
+our $opt_skip_ssl;
+our $opt_ssl_supported;
+our $opt_ps_protocol;
+our $opt_sp_protocol;
+our $opt_cursor_protocol;
+our $opt_view_protocol;
+
our $opt_debug;
our $opt_do_test;
our @opt_cases; # The test cases names in argv
@@ -198,53 +207,60 @@ our $opt_embedded_server;
our $opt_extern;
our $opt_fast;
our $opt_force;
-our $opt_reorder;
+our $opt_reorder= 0;
+our $opt_enable_disabled;
our $opt_gcov;
our $opt_gcov_err;
our $opt_gcov_msg;
+our $glob_debugger= 0;
our $opt_gdb;
our $opt_client_gdb;
+our $opt_ddd;
+our $opt_client_ddd;
our $opt_manual_gdb;
+our $opt_manual_ddd;
+our $opt_manual_debug;
+our $opt_debugger;
+our $opt_client_debugger;
our $opt_gprof;
our $opt_gprof_dir;
our $opt_gprof_master;
our $opt_gprof_slave;
-our $opt_local;
-our $opt_local_master;
-
-our $master; # Will be struct in C
+our $master;
our $slave;
+our $clusters;
+
+our $instance_manager;
our $opt_ndbcluster_port;
our $opt_ndbconnectstring;
-
-our $opt_no_manager; # Does nothing now, we never use manager
-our $opt_manager_port; # Does nothing now, we never use manager
-
-our $opt_old_master;
+our $opt_ndbcluster_port_slave;
+our $opt_ndbconnectstring_slave;
our $opt_record;
+our $opt_check_testcases;
our $opt_result_ext;
our $opt_skip;
our $opt_skip_rpl;
-our $opt_skip_im; # --skip-im on command line will just be ignored
+our $max_slave_num= 0;
+our $use_innodb;
our $opt_skip_test;
+our $opt_skip_im;
our $opt_sleep;
-our $opt_ps_protocol;
our $opt_sleep_time_after_restart= 1;
our $opt_sleep_time_for_delete= 10;
our $opt_testcase_timeout;
our $opt_suite_timeout;
my $default_testcase_timeout= 15; # 15 min max
-my $default_suite_timeout= 120; # 2 hours max
+my $default_suite_timeout= 180; # 3 hours max
our $opt_socket;
@@ -256,18 +272,28 @@ our $opt_start_from;
our $opt_strace_client;
-our $opt_timer;
+our $opt_timer= 1;
our $opt_user;
our $opt_user_test;
-our $opt_valgrind;
-our $opt_valgrind_mysqld;
-our $opt_valgrind_mysqltest;
-our $opt_valgrind_all;
+our $opt_valgrind= 0;
+our $opt_valgrind_mysqld= 0;
+our $opt_valgrind_mysqltest= 0;
+our $default_valgrind_options= "--show-reachable=yes";
our $opt_valgrind_options;
-
-our $opt_verbose;
+our $opt_valgrind_path;
+our $opt_callgrind;
+
+our $opt_stress= "";
+our $opt_stress_suite= "main";
+our $opt_stress_mode= "random";
+our $opt_stress_threads= 5;
+our $opt_stress_test_count= 0;
+our $opt_stress_loop_count= 0;
+our $opt_stress_test_duration= 0;
+our $opt_stress_init_file= "";
+our $opt_stress_test_file= "";
our $opt_wait_for_master;
our $opt_wait_for_slave;
@@ -277,17 +303,30 @@ our $opt_warnings;
our $opt_udiff;
-our $opt_skip_ndbcluster;
-our $opt_with_ndbcluster;
-our $opt_with_ndbcluster_only= 0; # dummy, ignored
-
-our $opt_with_openssl;
+our $opt_skip_ndbcluster= 0;
+our $opt_skip_ndbcluster_slave= 0;
+our $opt_with_ndbcluster= 0;
+our $opt_with_ndbcluster_only= 0;
+our $opt_ndbcluster_supported= 0;
+our $opt_ndb_extra_test= 0;
+our $opt_skip_master_binlog= 0;
+our $opt_skip_slave_binlog= 0;
our $exe_ndb_mgm;
+our $exe_ndb_waiter;
our $path_ndb_tools_dir;
-our $path_ndb_backup_dir;
-our $file_ndb_testrun_log;
-our $flag_ndb_status_ok= 1;
+our $path_ndb_examples_dir;
+our $exe_ndb_example;
+our $path_ndb_testrun_log;
+
+our @data_dir_lst;
+
+our $used_binlog_format;
+our $debug_compiled_binaries;
+our $glob_tot_real_time= 0;
+
+# Default values read from mysqld
+our $default_mysqld_port;
######################################################################
#
@@ -298,27 +337,36 @@ our $flag_ndb_status_ok= 1;
sub main ();
sub initial_setup ();
sub command_line_setup ();
+sub snapshot_setup ();
sub executable_setup ();
sub environment_setup ();
sub kill_running_server ();
-sub kill_and_cleanup ();
-sub ndbcluster_support ();
-sub ndbcluster_install ();
-sub ndbcluster_start ();
-sub ndbcluster_stop ();
+sub cleanup_stale_files ();
+sub check_ssl_support ($);
+sub check_running_as_root();
+sub check_ndbcluster_support ($);
+sub rm_ndbcluster_tables ($);
+sub ndbcluster_start_install ($);
+sub ndbcluster_start ($$);
+sub ndbcluster_wait_started ($$);
+sub mysqld_wait_started($);
sub run_benchmarks ($);
-sub run_tests ();
+sub initialize_servers ();
sub mysql_install_db ();
sub install_db ($$);
+sub copy_install_db ($$);
sub run_testcase ($);
+sub run_testcase_stop_servers ($$$);
+sub run_testcase_start_servers ($);
+sub run_testcase_check_skip_test($);
sub report_failure_and_restart ($);
sub do_before_start_master ($$);
sub do_before_start_slave ($$);
-sub mysqld_start ($$$$);
+sub ndbd_start ($$$);
+sub ndb_mgmd_start ($);
+sub mysqld_start ($$$);
sub mysqld_arguments ($$$$$);
-sub stop_masters_slaves ();
-sub stop_masters ();
-sub stop_slaves ();
+sub stop_all_servers ();
sub run_mysqltest ($);
sub usage ($);
@@ -335,12 +383,6 @@ sub main () {
initial_setup();
command_line_setup();
executable_setup();
-
- if (! $opt_skip_ndbcluster and ! $opt_with_ndbcluster)
- {
- $opt_with_ndbcluster= ndbcluster_support();
- }
-
environment_setup();
signal_setup();
@@ -354,44 +396,44 @@ sub main () {
gprof_prepare();
}
- if ( ! $glob_use_running_server )
- {
- if ( $opt_start_dirty )
- {
- kill_running_server();
- }
- else
- {
- kill_and_cleanup();
- mysql_install_db();
-
-# mysql_loadstd(); FIXME copying from "std_data" .frm and
-# .MGR but there are none?!
- }
- }
-
- if ( $opt_start_dirty )
+ if ( $opt_bench )
{
- if ( ndbcluster_start() )
- {
- mtr_error("Can't start ndbcluster");
- }
- if ( mysqld_start('master',0,[],[]) )
- {
- mtr_report("Servers started, exiting");
- }
- else
- {
- mtr_error("Can't start the mysqld server");
- }
+ initialize_servers();
+ run_benchmarks(shift); # Shift what? Extra arguments?!
}
- elsif ( $opt_bench )
+ elsif ( $opt_stress )
{
- run_benchmarks(shift); # Shift what? Extra arguments?!
+ initialize_servers();
+ run_stress_test()
}
else
{
- run_tests();
+ # Figure out which tests we are going to run
+ my $tests= collect_test_cases($opt_suite);
+
+ # Turn off NDB and other similar options if no tests use it
+ my ($need_ndbcluster,$need_im);
+ foreach my $test (@$tests)
+ {
+ $need_ndbcluster||= $test->{ndb_test};
+ $need_im||= $test->{component_id} eq 'im';
+
+ # Count max number of slaves used by a test case
+ if ( $test->{slave_num} > $max_slave_num)
+ {
+ $max_slave_num= $test->{slave_num};
+ mtr_error("Too many slaves") if $max_slave_num > 3;
+ }
+ $use_innodb||= $test->{'innodb_test'};
+ }
+ $opt_skip_ndbcluster= $opt_skip_ndbcluster_slave= 1
+ unless $need_ndbcluster;
+ $opt_skip_im= 1 unless $need_im;
+
+ snapshot_setup();
+ initialize_servers();
+
+ run_suite($opt_suite, $tests);
}
mtr_exit(0);
@@ -410,13 +452,8 @@ sub initial_setup () {
$glob_scriptname= basename($0);
- $glob_win32_perl= ($^O eq "MSWin32");
- $glob_cygwin_perl= ($^O eq "cygwin");
- $glob_win32= ($glob_win32_perl or $glob_cygwin_perl);
-
# We require that we are in the "mysql-test" directory
# to run mysql-test-run
-
if (! -f $glob_scriptname)
{
mtr_error("Can't find the location for the mysql-test-run script\n" .
@@ -437,16 +474,13 @@ sub initial_setup () {
{
# Windows programs like 'mysqld' needs Windows paths
$glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`;
- my $shell= $ENV{'SHELL'} || "/bin/bash";
- $glob_cygwin_shell= `cygpath -w "$shell"`; # The Windows path c:\...
chomp($glob_mysql_test_dir);
- chomp($glob_cygwin_shell);
}
$glob_basedir= dirname($glob_mysql_test_dir);
- $glob_mysql_bench_dir= "$glob_basedir/mysql-bench"; # FIXME make configurable
- # needs to be same length to test logging (FIXME what???)
- $path_slave_load_tmpdir= "../../var/tmp";
+ # Expect mysql-bench to be located adjacent to the source tree, by default
+ $glob_mysql_bench_dir= "$glob_basedir/../mysql-bench"
+ unless defined $glob_mysql_bench_dir;
$path_my_basedir=
$opt_source_dist ? $glob_mysql_test_dir : $glob_basedir;
@@ -467,9 +501,15 @@ sub command_line_setup () {
# These are defaults for things that are set on the command line
$opt_suite= "main"; # Special default suite
- my $opt_master_myport= 9306;
- my $opt_slave_myport= 9308;
- $opt_ndbcluster_port= 9350;
+ my $opt_comment;
+
+ my $opt_master_myport= 9306;
+ my $opt_slave_myport= 9308;
+ $opt_ndbcluster_port= 9310;
+ $opt_ndbcluster_port_slave= 9311;
+ my $im_port= 9312;
+ my $im_mysqld1_port= 9313;
+ my $im_mysqld2_port= 9314;
#
# To make it easier for different devs to work on the same host,
@@ -488,9 +528,13 @@ sub command_line_setup () {
if ( $ENV{'MTR_BUILD_THREAD'} )
{
# Up to two masters, up to three slaves
- $opt_master_myport= $ENV{'MTR_BUILD_THREAD'} * 10 + 10000; # and 1
- $opt_slave_myport= $opt_master_myport + 2; # and 3 4
- $opt_ndbcluster_port= $opt_master_myport + 5;
+ $opt_master_myport= $ENV{'MTR_BUILD_THREAD'} * 10 + 10000; # and 1
+ $opt_slave_myport= $opt_master_myport + 2; # and 3 4
+ $opt_ndbcluster_port= $opt_master_myport + 5;
+ $opt_ndbcluster_port_slave= $opt_master_myport + 6;
+ $im_port= $opt_master_myport + 7;
+ $im_mysqld1_port= $opt_master_myport + 8;
+ $im_mysqld2_port= $opt_master_myport + 9;
}
if ( $opt_master_myport < 5001 or $opt_master_myport + 10 >= 32767 )
@@ -500,6 +544,11 @@ sub command_line_setup () {
"($opt_master_myport - $opt_master_myport + 10)");
}
+ # 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.
+ print "Logging: $0 ", join(" ", @ARGV), "\n";
+
# Read the command line
# Note: Keep list, and the order, in sync with usage at end of this file
@@ -508,42 +557,63 @@ sub command_line_setup () {
# Control what engine/variation to run
'embedded-server' => \$opt_embedded_server,
'ps-protocol' => \$opt_ps_protocol,
+ 'sp-protocol' => \$opt_sp_protocol,
+ 'view-protocol' => \$opt_view_protocol,
+ 'cursor-protocol' => \$opt_cursor_protocol,
+ 'ssl|with-openssl' => \$opt_ssl,
+ 'skip-ssl' => \$opt_skip_ssl,
+ 'compress' => \$opt_compress,
'bench' => \$opt_bench,
'small-bench' => \$opt_small_bench,
- 'no-manager' => \$opt_no_manager, # Currently not used
# Control what test suites or cases to run
'force' => \$opt_force,
'with-ndbcluster' => \$opt_with_ndbcluster,
- 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
'with-ndbcluster-only' => \$opt_with_ndbcluster_only,
+ 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
+ 'skip-ndbcluster-slave|skip-ndb-slave'
+ => \$opt_skip_ndbcluster_slave,
+ 'ndb-extra-test' => \$opt_ndb_extra_test,
+ 'skip-master-binlog' => \$opt_skip_master_binlog,
+ 'skip-slave-binlog' => \$opt_skip_slave_binlog,
'do-test=s' => \$opt_do_test,
+ 'start-from=s' => \$opt_start_from,
'suite=s' => \$opt_suite,
'skip-rpl' => \$opt_skip_rpl,
- 'skip-im' => \$opt_skip_im,
+ 'skip-im' => \$opt_skip_im,
'skip-test=s' => \$opt_skip_test,
+ 'big-test' => \$opt_big_test,
# Specify ports
'master_port=i' => \$opt_master_myport,
'slave_port=i' => \$opt_slave_myport,
- 'ndbcluster_port=i' => \$opt_ndbcluster_port,
- 'manager-port=i' => \$opt_manager_port, # Currently not used
+ 'ndbcluster-port|ndbcluster_port=i' => \$opt_ndbcluster_port,
+ 'ndbcluster-port-slave=i' => \$opt_ndbcluster_port_slave,
+ 'im-port=i' => \$im_port, # Instance Manager port.
+ 'im-mysqld1-port=i' => \$im_mysqld1_port, # Port of mysqld, controlled by IM
+ 'im-mysqld2-port=i' => \$im_mysqld2_port, # Port of mysqld, controlled by IM
# Test case authoring
'record' => \$opt_record,
+ 'check-testcases' => \$opt_check_testcases,
- # ???
+ # Extra options used when starting mysqld
'mysqld=s' => \@opt_extra_mysqld_opt,
# Run test on running server
'extern' => \$opt_extern,
- 'ndbconnectstring=s' => \$opt_ndbconnectstring,
+ 'ndb-connectstring=s' => \$opt_ndbconnectstring,
+ 'ndb-connectstring-slave=s' => \$opt_ndbconnectstring_slave,
# Debugging
'gdb' => \$opt_gdb,
- 'manual-gdb' => \$opt_manual_gdb,
'client-gdb' => \$opt_client_gdb,
+ 'manual-gdb' => \$opt_manual_gdb,
+ 'manual-debug' => \$opt_manual_debug,
'ddd' => \$opt_ddd,
+ 'client-ddd' => \$opt_client_ddd,
+ 'debugger=s' => \$opt_debugger,
+ 'client-debugger=s' => \$opt_client_debugger,
'strace-client' => \$opt_strace_client,
'master-binary=s' => \$exe_master_mysqld,
'slave-binary=s' => \$exe_slave_mysqld,
@@ -551,48 +621,54 @@ sub command_line_setup () {
# Coverage, profiling etc
'gcov' => \$opt_gcov,
'gprof' => \$opt_gprof,
- 'valgrind:s' => \$opt_valgrind,
- 'valgrind-mysqltest:s' => \$opt_valgrind_mysqltest,
- 'valgrind-all:s' => \$opt_valgrind_all,
+ 'valgrind|valgrind-all' => \$opt_valgrind,
+ 'valgrind-mysqltest' => \$opt_valgrind_mysqltest,
+ 'valgrind-mysqld' => \$opt_valgrind_mysqld,
'valgrind-options=s' => \$opt_valgrind_options,
+ 'valgrind-path=s' => \$opt_valgrind_path,
+ 'callgrind' => \$opt_callgrind,
+
+ # Stress testing
+ 'stress' => \$opt_stress,
+ 'stress-suite=s' => \$opt_stress_suite,
+ 'stress-threads=i' => \$opt_stress_threads,
+ 'stress-test-file=s' => \$opt_stress_test_file,
+ 'stress-init-file=s' => \$opt_stress_init_file,
+ 'stress-mode=s' => \$opt_stress_mode,
+ 'stress-loop-count=i' => \$opt_stress_loop_count,
+ 'stress-test-count=i' => \$opt_stress_test_count,
+ 'stress-test-duration=i' => \$opt_stress_test_duration,
+
+ # Directories
+ 'tmpdir=s' => \$opt_tmpdir,
+ 'vardir=s' => \$opt_vardir,
+ 'benchdir=s' => \$glob_mysql_bench_dir,
# Misc
- 'big-test' => \$opt_big_test,
'comment=s' => \$opt_comment,
- 'compress' => \$opt_compress,
'debug' => \$opt_debug,
'fast' => \$opt_fast,
- 'local' => \$opt_local,
- 'local-master' => \$opt_local_master,
- 'netware' => \$opt_netware,
- 'old-master' => \$opt_old_master,
'reorder' => \$opt_reorder,
+ 'enable-disabled' => \$opt_enable_disabled,
'script-debug' => \$opt_script_debug,
+ 'verbose' => \$opt_verbose,
'sleep=i' => \$opt_sleep,
'socket=s' => \$opt_socket,
'start-dirty' => \$opt_start_dirty,
'start-and-exit' => \$opt_start_and_exit,
- 'start-from=s' => \$opt_start_from,
- 'timer' => \$opt_timer,
- 'tmpdir=s' => \$opt_tmpdir,
+ 'timer!' => \$opt_timer,
'unified-diff|udiff' => \$opt_udiff,
'user-test=s' => \$opt_user_test,
'user=s' => \$opt_user,
- 'vardir=s' => \$opt_vardir,
- 'verbose' => \$opt_verbose,
'wait-timeout=i' => \$opt_wait_timeout,
'testcase-timeout=i' => \$opt_testcase_timeout,
'suite-timeout=i' => \$opt_suite_timeout,
'warnings|log-warnings' => \$opt_warnings,
- 'with-openssl' => \$opt_with_openssl,
'help|h' => \$opt_usage,
) or usage("Can't read options");
- if ( $opt_usage )
- {
- usage("");
- }
+ usage("") if $opt_usage;
if ( $opt_comment )
{
@@ -602,11 +678,6 @@ sub command_line_setup () {
print '#' x 78, "\n\n";
}
- if ( $opt_with_ndbcluster_only )
- {
- print "# Option '--with-ndbcluster-only' is ignored in this release.\n";
- }
-
foreach my $arg ( @ARGV )
{
if ( $arg =~ /^--skip-/ )
@@ -630,6 +701,21 @@ sub command_line_setup () {
}
# --------------------------------------------------------------------------
+ # Find out type of logging that are being used
+ # --------------------------------------------------------------------------
+
+ # NOTE if the default binlog format is changed, this has to be changed
+ $used_binlog_format= "stmt";
+ foreach my $arg ( @opt_extra_mysqld_opt )
+ {
+ if ( defined mtr_match_substring($arg,"binlog-format=row"))
+ {
+ $used_binlog_format= "row";
+ }
+ }
+ mtr_report("Using binlog format '$used_binlog_format'");
+
+ # --------------------------------------------------------------------------
# Set the "var/" directory, as it is the base for everything else
# --------------------------------------------------------------------------
@@ -637,6 +723,15 @@ sub command_line_setup () {
{
$opt_vardir= "$glob_mysql_test_dir/var";
}
+ elsif ( $mysql_version_id < 50000 )
+ {
+ # --vardir was specified
+ mtr_error("--vardir option not supported until MySQL 5.0");
+ }
+
+ $path_vardir_trace= $opt_vardir;
+ # Chop off any "c:", DBUG likes a unix path ex: c:/src/... => /src/...
+ $path_vardir_trace=~ s/^\w://;
# We make the path absolute, as the server will do a chdir() before usage
unless ( $opt_vardir =~ m,^/, or
@@ -652,27 +747,11 @@ sub command_line_setup () {
$opt_tmpdir= "$opt_vardir/tmp" unless $opt_tmpdir;
$opt_tmpdir =~ s,/+$,,; # Remove ending slash if any
- # FIXME maybe not needed?
- $path_manager_log= "$opt_vardir/log/manager.log"
- unless $path_manager_log;
- $opt_current_test= "$opt_vardir/log/current_test"
- unless $opt_current_test;
# --------------------------------------------------------------------------
# Do sanity checks of command line arguments
# --------------------------------------------------------------------------
- if ( $opt_extern and $opt_local )
- {
- mtr_error("Can't use --extern and --local at the same time");
- }
-
- if ( ! $opt_socket )
- { # FIXME set default before reading options?
-# $opt_socket= '@MYSQL_UNIX_ADDR@';
- $opt_socket= "/tmp/mysql.sock"; # FIXME
- }
-
# --------------------------------------------------------------------------
# Look at the command line options and set script flags
# --------------------------------------------------------------------------
@@ -687,7 +766,8 @@ sub command_line_setup () {
$glob_use_embedded_server= 1;
push(@glob_test_mode, "embedded");
$opt_skip_rpl= 1; # We never run replication with embedded
- $opt_skip_ndbcluster= 1;
+ $opt_skip_ndbcluster= 1; # Turn off use of NDB cluster
+ $opt_skip_ssl= 1; # Turn off use of SSL
if ( $opt_extern )
{
@@ -700,11 +780,40 @@ sub command_line_setup () {
push(@glob_test_mode, "ps-protocol");
}
- # FIXME don't understand what this is
-# if ( $opt_local_master )
-# {
-# $opt_master_myport= 3306;
-# }
+ if ( $opt_with_ndbcluster and $opt_skip_ndbcluster)
+ {
+ mtr_error("Can't specify both --with-ndbcluster and --skip-ndbcluster");
+ }
+
+ if ( $opt_ndbconnectstring )
+ {
+ $glob_use_running_ndbcluster= 1;
+ mtr_error("Can't specify --ndb-connectstring and --skip-ndbcluster")
+ if $opt_skip_ndbcluster;
+ mtr_error("Can't specify --ndb-connectstring and --ndbcluster-port")
+ if $opt_ndbcluster_port;
+ }
+ else
+ {
+ # Set default connect string
+ $opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
+ }
+
+ if ( $opt_ndbconnectstring_slave )
+ {
+ $glob_use_running_ndbcluster_slave= 1;
+ mtr_error("Can't specify ndb-connectstring_slave and " .
+ "--skip-ndbcluster-slave")
+ if $opt_skip_ndbcluster;
+ mtr_error("Can't specify --ndb-connectstring-slave and " .
+ "--ndbcluster-port-slave")
+ if $opt_ndbcluster_port_slave;
+ }
+ else
+ {
+ # Set default connect string
+ $opt_ndbconnectstring_slave= "host=localhost:$opt_ndbcluster_port_slave";
+ }
if ( $opt_small_bench )
{
@@ -721,83 +830,83 @@ sub command_line_setup () {
mtr_error("Coverage test needs the source - please use source dist");
}
- if ( $opt_gdb )
+ # Check debug related options
+ if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd ||
+ $opt_manual_gdb || $opt_manual_ddd || $opt_manual_debug ||
+ $opt_debugger || $opt_client_debugger )
{
+ # Indicate that we are using debugger
+ $glob_debugger= 1;
+ # Increase timeouts
$opt_wait_timeout= 300;
if ( $opt_extern )
{
- mtr_error("Can't use --extern with --gdb");
+ mtr_error("Can't use --extern when using debugger");
}
}
- if ( $opt_manual_gdb )
+ # Check IM arguments
+ if ( $glob_win32 )
{
- $opt_gdb= 1;
- if ( $opt_extern )
- {
- mtr_error("Can't use --extern with --manual-gdb");
- }
+ mtr_report("Disable Instance manager - not supported on Windows");
+ $opt_skip_im= 1;
}
-
- if ( $opt_ddd )
+ # Check valgrind arguments
+ if ( $opt_valgrind or $opt_valgrind_path or defined $opt_valgrind_options)
{
- if ( $opt_extern )
- {
- mtr_error("Can't use --extern with --ddd");
- }
+ mtr_report("Turning on valgrind for all executables");
+ $opt_valgrind= 1;
+ $opt_valgrind_mysqld= 1;
+ $opt_valgrind_mysqltest= 1;
}
-
- if ( $opt_ndbconnectstring )
+ elsif ( $opt_valgrind_mysqld )
{
- $glob_use_running_ndbcluster= 1;
- $opt_with_ndbcluster= 1;
+ mtr_report("Turning on valgrind for mysqld(s) only");
+ $opt_valgrind= 1;
}
- else
+ elsif ( $opt_valgrind_mysqltest )
{
- $opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
+ mtr_report("Turning on valgrind for mysqltest only");
+ $opt_valgrind= 1;
}
- if ( $opt_skip_ndbcluster )
+ if ( $opt_callgrind )
{
- $opt_with_ndbcluster= 0;
- }
+ mtr_report("Turning on valgrind with callgrind for mysqld(s)");
+ $opt_valgrind= 1;
+ $opt_valgrind_mysqld= 1;
- # The ":s" in the argument spec, means we have three different cases
- #
- # undefined option not set
- # "" option set with no argument
- # "somestring" option is name/path of valgrind executable
-
- # Take executable path from any of them, if any
- $opt_valgrind_mysqld= $opt_valgrind;
- $opt_valgrind= $opt_valgrind_mysqltest if $opt_valgrind_mysqltest;
- $opt_valgrind= $opt_valgrind_all if $opt_valgrind_all;
+ # Set special valgrind options unless options passed on command line
+ $opt_valgrind_options="--trace-children=yes"
+ unless defined $opt_valgrind_options;
+ }
- # If valgrind flag not defined, define if other valgrind flags are
- unless ( defined $opt_valgrind )
+ if ( $opt_valgrind )
{
- $opt_valgrind= ""
- if defined $opt_valgrind_mysqltest or defined $opt_valgrind_all;
+ # Set valgrind_options to default unless already defined
+ $opt_valgrind_options=$default_valgrind_options
+ unless defined $opt_valgrind_options;
+
+ mtr_report("Running valgrind with options \"$opt_valgrind_options\"");
}
if ( ! $opt_testcase_timeout )
{
$opt_testcase_timeout= $default_testcase_timeout;
- $opt_testcase_timeout*= 10 if defined $opt_valgrind;
+ $opt_testcase_timeout*= 10 if $opt_valgrind;
}
if ( ! $opt_suite_timeout )
{
$opt_suite_timeout= $default_suite_timeout;
- $opt_suite_timeout*= 4 if defined $opt_valgrind;
+ $opt_suite_timeout*= 6 if $opt_valgrind;
}
- if ( defined $opt_valgrind )
+ # Increase times to wait for executables to start if using valgrind
+ if ( $opt_valgrind )
{
$opt_sleep_time_after_restart= 10;
$opt_sleep_time_for_delete= 60;
- # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr
- # valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck"
}
if ( ! $opt_user )
@@ -812,74 +921,210 @@ sub command_line_setup () {
}
}
+ # On QNX, /tmp/dir/master.sock and /tmp/dir//master.sock seem to be
+ # considered different, so avoid the extra slash (/) in the socket
+ # paths.
+ my $sockdir = $opt_tmpdir;
+ $sockdir =~ s|/+$||;
+
# Put this into a hash, will be a C struct
$master->[0]=
{
+ pid => 0,
+ type => "master",
+ idx => 0,
path_myddir => "$opt_vardir/master-data",
path_myerr => "$opt_vardir/log/master.err",
path_mylog => "$opt_vardir/log/master.log",
- path_mypid => "$opt_vardir/run/master.pid",
- path_mysock => "$opt_tmpdir/master.sock",
- path_myport => $opt_master_myport,
+ path_pid => "$opt_vardir/run/master.pid",
+ path_sock => "$sockdir/master.sock",
+ port => $opt_master_myport,
start_timeout => 400, # enough time create innodb tables
-
- ndbcluster => 1, # ndbcluster not started
+ cluster => 0, # index in clusters list
+ start_opts => [],
};
$master->[1]=
{
+ pid => 0,
+ type => "master",
+ idx => 1,
path_myddir => "$opt_vardir/master1-data",
path_myerr => "$opt_vardir/log/master1.err",
path_mylog => "$opt_vardir/log/master1.log",
- path_mypid => "$opt_vardir/run/master1.pid",
- path_mysock => "$opt_tmpdir/master1.sock",
- path_myport => $opt_master_myport + 1,
+ path_pid => "$opt_vardir/run/master1.pid",
+ path_sock => "$sockdir/master1.sock",
+ port => $opt_master_myport + 1,
start_timeout => 400, # enough time create innodb tables
+ cluster => 0, # index in clusters list
+ start_opts => [],
};
$slave->[0]=
{
+ pid => 0,
+ type => "slave",
+ idx => 0,
path_myddir => "$opt_vardir/slave-data",
path_myerr => "$opt_vardir/log/slave.err",
path_mylog => "$opt_vardir/log/slave.log",
- path_mypid => "$opt_vardir/run/slave.pid",
- path_mysock => "$opt_tmpdir/slave.sock",
- path_myport => $opt_slave_myport,
+ path_pid => "$opt_vardir/run/slave.pid",
+ path_sock => "$sockdir/slave.sock",
+ port => $opt_slave_myport,
start_timeout => 400,
+
+ cluster => 1, # index in clusters list
+ start_opts => [],
};
$slave->[1]=
{
+ pid => 0,
+ type => "slave",
+ idx => 1,
path_myddir => "$opt_vardir/slave1-data",
path_myerr => "$opt_vardir/log/slave1.err",
path_mylog => "$opt_vardir/log/slave1.log",
- path_mypid => "$opt_vardir/run/slave1.pid",
- path_mysock => "$opt_tmpdir/slave1.sock",
- path_myport => $opt_slave_myport + 1,
+ path_pid => "$opt_vardir/run/slave1.pid",
+ path_sock => "$sockdir/slave1.sock",
+ port => $opt_slave_myport + 1,
start_timeout => 300,
+ cluster => -1, # index in clusters list
+ start_opts => [],
};
$slave->[2]=
{
+ pid => 0,
+ type => "slave",
+ idx => 2,
path_myddir => "$opt_vardir/slave2-data",
path_myerr => "$opt_vardir/log/slave2.err",
path_mylog => "$opt_vardir/log/slave2.log",
- path_mypid => "$opt_vardir/run/slave2.pid",
- path_mysock => "$opt_tmpdir/slave2.sock",
- path_myport => $opt_slave_myport + 2,
+ path_pid => "$opt_vardir/run/slave2.pid",
+ path_sock => "$sockdir/slave2.sock",
+ port => $opt_slave_myport + 2,
start_timeout => 300,
+ cluster => -1, # index in clusters list
+ start_opts => [],
+ };
+
+ $instance_manager=
+ {
+ path_err => "$opt_vardir/log/im.err",
+ path_log => "$opt_vardir/log/im.log",
+ path_pid => "$opt_vardir/run/im.pid",
+ path_angel_pid => "$opt_vardir/run/im.angel.pid",
+ path_sock => "$sockdir/im.sock",
+ port => $im_port,
+ start_timeout => $master->[0]->{'start_timeout'},
+ admin_login => 'im_admin',
+ admin_password => 'im_admin_secret',
+ admin_sha1 => '*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295',
+ password_file => "$opt_vardir/im.passwd",
+ defaults_file => "$opt_vardir/im.cnf",
+ };
+
+ $instance_manager->{'instances'}->[0]=
+ {
+ server_id => 1,
+ port => $im_mysqld1_port,
+ path_datadir => "$opt_vardir/im_mysqld_1.data",
+ path_sock => "$sockdir/mysqld_1.sock",
+ path_pid => "$opt_vardir/run/mysqld_1.pid",
+ start_timeout => 400, # enough time create innodb tables
+ old_log_format => 1
+ };
+
+ $instance_manager->{'instances'}->[1]=
+ {
+ server_id => 2,
+ port => $im_mysqld2_port,
+ path_datadir => "$opt_vardir/im_mysqld_2.data",
+ path_sock => "$sockdir/mysqld_2.sock",
+ path_pid => "$opt_vardir/run/mysqld_2.pid",
+ nonguarded => 1,
+ start_timeout => 400, # enough time create innodb tables
+ old_log_format => 1
+ };
+
+ my $data_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port";
+ $clusters->[0]=
+ {
+ name => "Master",
+ nodes => 2,
+ port => "$opt_ndbcluster_port",
+ data_dir => "$data_dir",
+ connect_string => "$opt_ndbconnectstring",
+ path_pid => "$data_dir/ndb_3.pid", # Nodes + 1
+ pid => 0, # pid of ndb_mgmd
+ installed_ok => 0,
};
+ $data_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port_slave";
+ $clusters->[1]=
+ {
+ name => "Slave",
+ nodes => 1,
+ port => "$opt_ndbcluster_port_slave",
+ data_dir => "$data_dir",
+ connect_string => "$opt_ndbconnectstring_slave",
+ path_pid => "$data_dir/ndb_2.pid", # Nodes + 1
+ pid => 0, # pid of ndb_mgmd
+ installed_ok => 0,
+ };
+
+ # Init pids of ndbd's
+ foreach my $cluster ( @{$clusters} )
+ {
+ for ( my $idx= 0; $idx < $cluster->{'nodes'}; $idx++ )
+ {
+ my $nodeid= $idx+1;
+ $cluster->{'ndbds'}->[$idx]=
+ {
+ pid => 0,
+ nodeid => $nodeid,
+ path_pid => "$cluster->{'data_dir'}/ndb_${nodeid}.pid",
+ path_fs => "$cluster->{'data_dir'}/ndb_${nodeid}_fs",
+ };
+ }
+ }
+
if ( $opt_extern )
{
$glob_use_running_server= 1;
$opt_skip_rpl= 1; # We don't run rpl test cases
- $master->[0]->{'path_mysock'}= $opt_socket;
+ $master->[0]->{'path_sock'}= $opt_socket;
}
$path_timefile= "$opt_vardir/log/mysqltest-time";
$path_mysqltest_log= "$opt_vardir/log/mysqltest.log";
+ $path_current_test_log= "$opt_vardir/log/current_test";
+ $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
+
+ $path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/";
+}
+
+sub snapshot_setup () {
+
+ # Make a list of all data_dirs
+ @data_dir_lst = (
+ $master->[0]->{'path_myddir'},
+ $master->[1]->{'path_myddir'});
+
+ for (my $idx= 0; $idx < $max_slave_num; $idx++)
+ {
+ push(@data_dir_lst, $slave->[$idx]->{'path_myddir'});
+ }
+
+ unless ($opt_skip_im)
+ {
+ foreach my $instance (@{$instance_manager->{'instances'}})
+ {
+ push(@data_dir_lst, $instance->{'path_datadir'});
+ }
+ }
}
@@ -889,136 +1134,222 @@ sub command_line_setup () {
#
##############################################################################
-sub executable_setup () {
- if ( $opt_source_dist )
+sub check_mysqld_features () {
+ #
+ # Execute "mysqld --no-defaults --help --verbose", that will
+ # print out version and a list of all features and settings
+ #
+ my $found_variable_list_start= 0;
+ my $spec_file= "$opt_vardir/tmp/mysqld.spec";
+ if ( mtr_run($exe_mysqld,
+ ["--no-defaults",
+ "--verbose",
+ "--help"],
+ "", "$spec_file", "$spec_file", "") != 0 )
{
- if ( $glob_win32 )
- {
- $path_client_bindir= mtr_path_exists("$glob_basedir/client_release",
- "$glob_basedir/bin");
- $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt",
- "$path_client_bindir/mysqld",
- "$path_client_bindir/mysqld-debug",
- "$path_client_bindir/mysqld-max",
- "$path_client_bindir/mysqld-max-nt");
- $path_language= mtr_path_exists("$glob_basedir/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets");
- $exe_my_print_defaults=
- mtr_exe_exists("$path_client_bindir/my_print_defaults");
- }
- else
- {
- $path_client_bindir= mtr_path_exists("$glob_basedir/client");
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld");
- $path_language= mtr_path_exists("$glob_basedir/sql/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/sql/share/charsets");
- $exe_my_print_defaults=
- mtr_exe_exists("$glob_basedir/extra/my_print_defaults");
- }
+ mtr_error("Failed to get version and list of features from %s",
+ $exe_mysqld);
+ }
- if ( $glob_use_embedded_server )
+ my %mysqld_variables;
+ my $F= IO::File->new($spec_file) or
+ mtr_error("can't open file \"$spec_file\": $!");
+
+ while ( my $line= <$F> )
+ {
+ # First look for version
+ if ( !$mysql_version_id )
{
- my $path_examples= "$glob_basedir/libmysqld/examples";
- $exe_mysqltest= mtr_exe_exists("$path_examples/mysqltest_embedded");
- $exe_mysql_client_test=
- mtr_exe_exists("$path_examples/mysql_client_test_embedded",
- "/usr/bin/false");
+ # Look for version
+ if ( $line =~ /^$exe_mysqld\s\sVer\s([0-9]*)\.([0-9]*)\.([0-9]*)/ )
+ {
+ print "Major: $1 Minor: $2 Build: $3\n";
+ $mysql_version_id= $1*10000 + $2*100 + $3;
+ print "mysql_version_id: $mysql_version_id\n";
+ }
}
else
{
- if ( $opt_valgrind_mysqltest )
+ if (!$found_variable_list_start)
{
- # client/mysqltest might be a libtool .sh script, so look for real exe
- # to avoid valgrinding bash ;)
- $exe_mysqltest=
- mtr_exe_exists("$path_client_bindir/.libs/lt-mysqltest",
- "$path_client_bindir/.libs/mysqltest",
- "$path_client_bindir/mysqltest");
- }
- else
- {
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
+ # Look for start of variables list
+ if ( $line =~ /-*\s-*/ )
+ {
+ $found_variable_list_start= 1;
+ }
+ } else {
+ # Put variables into hash
+ if ( $line =~ /^(\w*)[ \t]*(\w*)$/ )
+ {
+ $mysqld_variables{$1}= $2;
+ }
}
- $exe_mysql_client_test=
- mtr_exe_exists("$glob_basedir/tests/mysql_client_test",
- "/usr/bin/false");
- }
- $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
- $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
- $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
- $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
- $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
- $exe_mysql_fix_system_tables=
- mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables");
- $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools");
- $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm";
+ }
}
- else
+ mtr_error("Could not find version of MySQL") unless $mysql_version_id;
+
+ check_ndbcluster_support(\%mysqld_variables);
+ check_ssl_support(\%mysqld_variables);
+ check_debug_support(\%mysqld_variables);
+
+ if ( $mysql_version_id < 50000 )
{
- $path_client_bindir= mtr_path_exists("$glob_basedir/bin");
- $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
- $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
- $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
- $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
- $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
- $exe_mysql_fix_system_tables=
- mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables",
- "$glob_basedir/scripts/mysql_fix_privilege_tables");
- $exe_my_print_defaults=
- mtr_exe_exists("$path_client_bindir/my_print_defaults");
-
- $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/",
- "$glob_basedir/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/share/mysql/charsets",
- "$glob_basedir/share/charsets");
-
- if ( $glob_win32 )
- {
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/bin/mysqld-nt",
- "$glob_basedir/bin/mysqld",
- "$glob_basedir/bin/mysqld-debug",);
- }
- else
- {
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld",
- "$glob_basedir/bin/mysqld");
- }
+ # Instance manager is not supported until 5.0
+ $opt_skip_im= 1;
+ }
- if ( $glob_use_embedded_server )
- {
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded");
- $exe_mysql_client_test=
- mtr_exe_exists("$glob_basedir/tests/mysql_client_test_embedded",
- "$path_client_bindir/mysql_client_test_embedded",
- "/usr/bin/false");
- }
- else
+ # Set default values from mysqld_variables
+ $opt_socket= %mysqld_variables->{'socket'};
+ $default_mysqld_port = %mysqld_variables->{'port'};
+}
+
+
+sub executable_setup () {
+
+ #
+ # 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)
{
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
- $exe_mysql_client_test=
- mtr_exe_exists("$path_client_bindir/mysql_client_test",
- "/usr/bin/false"); # FIXME temporary
+ mtr_report("Using \"$exe_libtool\" when running valgrind or debugger");
}
-
- $path_ndb_tools_dir= "$glob_basedir/bin";
- $exe_ndb_mgm= "$glob_basedir/bin/ndb_mgm";
}
+ # Look for the path where to find the client binaries
+ $path_client_bindir= mtr_path_exists("$glob_basedir/client",
+ "$glob_basedir/client_release",
+ "$glob_basedir/client_debug",
+ "$glob_basedir/client/release",
+ "$glob_basedir/client/debug",
+ "$glob_basedir/bin");
+
+ # Look for the mysqld executable
+ $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld",
+ "$path_client_bindir/mysqld-max-nt",
+ "$path_client_bindir/mysqld-max",
+ "$path_client_bindir/mysqld-nt",
+ "$path_client_bindir/mysqld",
+ "$path_client_bindir/mysqld-debug",
+ "$path_client_bindir/mysqld-max",
+ "$glob_basedir/libexec/mysqld",
+ "$glob_basedir/sql/release/mysqld",
+ "$glob_basedir/sql/debug/mysqld");
+
$exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
$exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld;
- $path_ndb_backup_dir=
- "$opt_vardir/ndbcluster-$opt_ndbcluster_port";
- $file_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
+ # Use the mysqld found above to find out what features are available
+ check_mysqld_features();
+
+ # Look for language files and charsetsdir, use same share
+ my $path_share= mtr_path_exists("$glob_basedir/share",
+ "$glob_basedir/sql/share",
+ "$glob_basedir/share/mysql",
+ "$glob_basedir/share");
+
+ $path_language= mtr_path_exists("$path_share/english");
+ $path_charsetsdir= mtr_path_exists("$path_share/charsets");
+
+ # Look for my_print_defaults
+ $exe_my_print_defaults=
+ mtr_exe_exists("$path_client_bindir/my_print_defaults",
+ "$glob_basedir/extra/my_print_defaults",
+ "$glob_basedir/extra/release/my_print_defaults",
+ "$glob_basedir/extra/debug/my_print_defaults");
+
+ # Look for perror
+ $exe_perror= mtr_exe_exists("$glob_basedir/extra/perror",
+ "$path_client_bindir/perror",
+ "$glob_basedir/extra/release/perror",
+ "$glob_basedir/extra/debug/perror");
+
+
+ if ( ! $opt_skip_im )
+ {
+ # Look for instance manager binary - mysqlmanager
+ $exe_im=
+ mtr_exe_exists(
+ "$glob_basedir/server-tools/instance-manager/mysqlmanager",
+ "$glob_basedir/libexec/mysqlmanager");
+ }
+
+ # Look for the client binaries
+ $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
+ $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
+ $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
+ $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
+ $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
+ $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
+ $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
+
+ # Look for mysql_fix_system_table script
+ $exe_mysql_fix_system_tables=
+ mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables",
+ "$path_client_bindir/mysql_fix_privilege_tables");
+
+ if ( $opt_with_ndbcluster)
+ {
+ # Look for ndb tols and binaries
+ $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools",
+ "$glob_basedir/bin");
+ $exe_ndb_mgm= mtr_exe_exists("$glob_basedir/ndb/src/mgmclient/ndb_mgm",
+ "$glob_basedir/bin/ndb_mgm");
+ }
+
+ # Look for the udf_example library
+ $lib_udf_example=
+ mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so");
+
+
+ # Look for mysqltest executable
+ if ( $glob_use_embedded_server )
+ {
+ $exe_mysqltest=
+ mtr_exe_exists("$glob_basedir/libmysqld/examples/mysqltest_embedded",
+ "$path_client_bindir/mysqltest_embedded");
+ }
+ else
+ {
+ $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
+
+
+ }
+
+ # Look for mysql_client_test executable
+ if ( $glob_use_embedded_server )
+ {
+ $exe_mysql_client_test=
+ mtr_exe_exists("$glob_basedir/libmysqld/examples/mysql_client_test_embedded",
+ "$glob_basedir/tests/mysqltest_embedded");
+ }
+ else
+ {
+ $exe_mysql_client_test=
+ mtr_exe_exists("$glob_basedir/tests/mysql_client_test");
+ }
+}
+
+
+sub generate_cmdline_mysqldump ($) {
+ my($mysqld) = @_;
+ return
+ "$exe_mysqldump --no-defaults -uroot " .
+ "--port=$mysqld->{'port'} " .
+ "--socket=$mysqld->{'path_sock'} --password=";
}
##############################################################################
#
-# Set environment to be used by childs of this process
+# Set environment to be used by childs of this process for
+# things that are constant duting the whole lifetime of mysql-test-run.pl
#
##############################################################################
@@ -1026,65 +1357,320 @@ sub executable_setup () {
sub environment_setup () {
+ umask(022);
+
+ my @ld_library_paths;
+
# --------------------------------------------------------------------------
- # We might not use a standard installation directory, like /usr/lib.
- # Set LD_LIBRARY_PATH to make sure we find our installed libraries.
+ # Setup LD_LIBRARY_PATH so the libraries from this distro/clone
+ # are used in favor of the system installed ones
# --------------------------------------------------------------------------
+ if ( $opt_source_dist )
+ {
+ push(@ld_library_paths, "$glob_basedir/libmysql/.libs/",
+ "$glob_basedir/libmysql_r/.libs/");
+ }
+ else
+ {
+ push(@ld_library_paths, "$glob_basedir/lib");
+ }
- unless ( $opt_source_dist )
+ # --------------------------------------------------------------------------
+ # Add the path where libndbclient can be found
+ # --------------------------------------------------------------------------
+ if ( $opt_ndbcluster_supported )
+ {
+ push(@ld_library_paths, "$glob_basedir/storage/ndb/src/.libs");
+ }
+
+ # --------------------------------------------------------------------------
+ # Add the path where mysqld will find udf_example.so
+ # --------------------------------------------------------------------------
+ if ( $lib_udf_example )
+ {
+ push(@ld_library_paths, dirname($lib_udf_example));
+ }
+
+ # --------------------------------------------------------------------------
+ # Valgrind need to be run with debug libraries otherwise it's almost
+ # impossible to add correct supressions, that means if "/usr/lib/debug"
+ # is available, it should be added to
+ # LD_LIBRARY_PATH
+ # --------------------------------------------------------------------------
+ my $debug_libraries_path= "/usr/lib/debug";
+ if ( $opt_valgrind and -d $debug_libraries_path )
{
- $ENV{'LD_LIBRARY_PATH'}=
- "$glob_basedir/lib" .
- ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
- $ENV{'DYLD_LIBRARY_PATH'}=
- "$glob_basedir/lib" .
- ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : "");
+ push(@ld_library_paths, $debug_libraries_path);
}
+ $ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths,
+ split(':', $ENV{'LD_LIBRARY_PATH'}));
+ mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}");
+
+ $ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths,
+ split(':', $ENV{'DYLD_LIBRARY_PATH'}));
+ mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}");
+
+
# --------------------------------------------------------------------------
# Also command lines in .opt files may contain env vars
# --------------------------------------------------------------------------
+ $ENV{'CHARSETSDIR'}= $path_charsetsdir;
$ENV{'UMASK'}= "0660"; # The octal *string*
$ENV{'UMASK_DIR'}= "0770"; # The octal *string*
$ENV{'LC_COLLATE'}= "C";
$ENV{'USE_RUNNING_SERVER'}= $glob_use_running_server;
$ENV{'MYSQL_TEST_DIR'}= $glob_mysql_test_dir;
- $ENV{'MYSQL_TEST_WINDIR'}= $glob_mysql_test_dir;
$ENV{'MYSQLTEST_VARDIR'}= $opt_vardir;
- $ENV{'MASTER_WINMYSOCK'}= $master->[0]->{'path_mysock'};
- $ENV{'MASTER_MYSOCK'}= $master->[0]->{'path_mysock'};
- $ENV{'MASTER_MYSOCK1'}= $master->[1]->{'path_mysock'};
- $ENV{'MASTER_MYPORT'}= $master->[0]->{'path_myport'};
- $ENV{'MASTER_MYPORT1'}= $master->[1]->{'path_myport'};
- $ENV{'SLAVE_MYPORT'}= $slave->[0]->{'path_myport'};
- $ENV{'SLAVE_MYPORT1'}= $slave->[1]->{'path_myport'};
- $ENV{'SLAVE_MYPORT2'}= $slave->[2]->{'path_myport'};
-# $ENV{'MYSQL_TCP_PORT'}= '@MYSQL_TCP_PORT@'; # FIXME
- $ENV{'MYSQL_TCP_PORT'}= 3306;
-
- $ENV{'NDBCLUSTER_PORT'}= $opt_ndbcluster_port;
+ $ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir;
+ $ENV{'MASTER_MYSOCK'}= $master->[0]->{'path_sock'};
+ $ENV{'MASTER_MYSOCK1'}= $master->[1]->{'path_sock'};
+ $ENV{'MASTER_MYPORT'}= $master->[0]->{'port'};
+ $ENV{'MASTER_MYPORT1'}= $master->[1]->{'port'};
+ $ENV{'SLAVE_MYSOCK'}= $slave->[0]->{'path_sock'};
+ $ENV{'SLAVE_MYPORT'}= $slave->[0]->{'port'};
+ $ENV{'SLAVE_MYPORT1'}= $slave->[1]->{'port'};
+ $ENV{'SLAVE_MYPORT2'}= $slave->[2]->{'port'};
+ $ENV{'MYSQL_TCP_PORT'}= $default_mysqld_port;
- if ( $glob_cygwin_perl )
+ $ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set
+
+ # ----------------------------------------------------
+ # Setup env for NDB
+ # ----------------------------------------------------
+ $ENV{'NDB_MGM'}= $exe_ndb_mgm;
+
+ $ENV{'NDBCLUSTER_PORT'}= $opt_ndbcluster_port;
+ $ENV{'NDBCLUSTER_PORT_SLAVE'}= $opt_ndbcluster_port_slave;
+
+ $ENV{'NDB_EXTRA_TEST'}= $opt_ndb_extra_test;
+
+ $ENV{'NDB_BACKUP_DIR'}= $clusters->[0]->{'data_dir'};
+ $ENV{'NDB_DATA_DIR'}= $clusters->[0]->{'data_dir'};
+ $ENV{'NDB_TOOLS_DIR'}= $path_ndb_tools_dir;
+ $ENV{'NDB_TOOLS_OUTPUT'}= $path_ndb_testrun_log;
+ $ENV{'NDB_CONNECTSTRING'}= $opt_ndbconnectstring;
+
+ $ENV{'NDB_EXAMPLES_DIR'}= $path_ndb_examples_dir;
+ $ENV{'MY_NDB_EXAMPLES_BINARY'}= $exe_ndb_example;
+ $ENV{'NDB_EXAMPLES_OUTPUT'}= $path_ndb_testrun_log;
+
+ # ----------------------------------------------------
+ # Setup env for IM
+ # ----------------------------------------------------
+ $ENV{'IM_EXE'}= $exe_im;
+ $ENV{'IM_PATH_PID'}= $instance_manager->{path_pid};
+ $ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid};
+ $ENV{'IM_PORT'}= $instance_manager->{port};
+ $ENV{'IM_DEFAULTS_PATH'}= $instance_manager->{defaults_file};
+ $ENV{'IM_PASSWORD_PATH'}= $instance_manager->{password_file};
+
+ $ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
+ $ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port};
+ $ENV{'IM_MYSQLD1_PATH_PID'}=$instance_manager->{instances}->[0]->{path_pid};
+ $ENV{'IM_MYSQLD2_SOCK'}= $instance_manager->{instances}->[1]->{path_sock};
+ $ENV{'IM_MYSQLD2_PORT'}= $instance_manager->{instances}->[1]->{port};
+ $ENV{'IM_MYSQLD2_PATH_PID'}=$instance_manager->{instances}->[1]->{path_pid};
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlcheck
+ # ----------------------------------------------------
+ my $cmdline_mysqlcheck=
+ "$exe_mysqlcheck --no-defaults -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password=";
+
+ if ( $opt_debug )
{
- foreach my $key ('MYSQL_TEST_WINDIR','MASTER_MYSOCK')
+ $cmdline_mysqlcheck .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlcheck.trace";
+ }
+ $ENV{'MYSQL_CHECK'}= $cmdline_mysqlcheck;
+
+ # ----------------------------------------------------
+ # Setup env to childs can execute myqldump
+ # ----------------------------------------------------
+ my $cmdline_mysqldump= generate_cmdline_mysqldump($master->[0]);
+ my $cmdline_mysqldumpslave= generate_cmdline_mysqldump($slave->[0]);
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqldump .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqldump-master.trace";
+ $cmdline_mysqldumpslave .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqldump-slave.trace";
+ }
+ $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
+ $ENV{'MYSQL_DUMP_SLAVE'}= $cmdline_mysqldumpslave;
+
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlslap
+ # ----------------------------------------------------
+ unless ( $glob_win32 )
+ {
+ my $cmdline_mysqlslap=
+ "$exe_mysqlslap -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password= " .
+ "--lock-directory=$opt_tmpdir";
+
+ if ( $opt_debug )
{
- $ENV{$key}= `cygpath -w $ENV{$key}`;
- $ENV{$key} =~ s,\\,\\\\,g;
- chomp($ENV{$key});
+ $cmdline_mysqlslap .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlslap.trace";
}
+ $ENV{'MYSQL_SLAP'}= $cmdline_mysqlslap;
}
- $ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlimport
+ # ----------------------------------------------------
+ my $cmdline_mysqlimport=
+ "$exe_mysqlimport -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password=";
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlimport .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlimport.trace";
+ }
+ $ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport;
+
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlshow
+ # ----------------------------------------------------
+ my $cmdline_mysqlshow=
+ "$exe_mysqlshow -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password=";
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlshow .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlshow.trace";
+ }
+ $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlbinlog
+ # ----------------------------------------------------
+ my $cmdline_mysqlbinlog=
+ "$exe_mysqlbinlog" .
+ " --no-defaults --local-load=$opt_tmpdir";
+ if ( $mysql_version_id >= 50000 )
+ {
+ $cmdline_mysqlbinlog .=" --character-sets-dir=$path_charsetsdir";
+ }
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlbinlog .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlbinlog.trace";
+ }
+ $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysql
+ # ----------------------------------------------------
+ my $cmdline_mysql=
+ "$exe_mysql --no-defaults --host=localhost --user=root --password= " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} ".
+ "--character-sets-dir=$path_charsetsdir";
+ $ENV{'MYSQL'}= $cmdline_mysql;
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysql_client_test
+ # ----------------------------------------------------
+ my $cmdline_mysql_client_test=
+ "$exe_mysql_client_test --no-defaults --testcase --user=root --silent " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'}";
+ if ( $mysql_version_id >= 50000 )
+ {
+ $cmdline_mysql_client_test .=" --vardir=$opt_vardir";
+ }
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysql_client_test .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysql_client_test.trace";
+ }
+
+ if ( $glob_use_embedded_server )
+ {
+ $cmdline_mysql_client_test.=
+ " -A --language=$path_language" .
+ " -A --datadir=$slave->[0]->{'path_myddir'}" .
+ " -A --character-sets-dir=$path_charsetsdir";
+ }
+ $ENV{'MYSQL_CLIENT_TEST'}= $cmdline_mysql_client_test;
+
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysql_fix_system_tables
+ # ----------------------------------------------------
+ my $cmdline_mysql_fix_system_tables=
+ "$exe_mysql_fix_system_tables --no-defaults --host=localhost --user=root --password= " .
+ "--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'}";
+
+ $ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables;
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute my_print_defaults
+ # ----------------------------------------------------
+ $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults;
+
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute perror
+ # ----------------------------------------------------
+ $ENV{'MY_PERROR'}= $exe_perror;
+
+ # ----------------------------------------------------
+ # Add the path where mysqld will find udf_example.so
+ # ----------------------------------------------------
+ $ENV{'UDF_EXAMPLE_LIB'}=
+ ($lib_udf_example ? basename($lib_udf_example) : "");
+
+ $ENV{'LD_LIBRARY_PATH'}=
+ ($lib_udf_example ? dirname($lib_udf_example) : "") .
+ ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
+
+
+ # ----------------------------------------------------
# We are nice and report a bit about our settings
- print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
- print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
- print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
- print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
- print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
- print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
- print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
+ # ----------------------------------------------------
+ if (!$opt_extern)
+ {
+ print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
+ print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
+ print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
+ print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
+ print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
+ print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
+ if ( ! $opt_skip_ndbcluster )
+ {
+ print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
+ if ( ! $opt_skip_ndbcluster_slave )
+ {
+ print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
+ }
+ }
+ if ( ! $opt_skip_im )
+ {
+ print "Using IM_PORT = $ENV{IM_PORT}\n";
+ print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
+ print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ }
+ }
}
@@ -1099,10 +1685,11 @@ sub signal_setup () {
$SIG{INT}= \&handle_int_signal;
}
+
sub handle_int_signal () {
$SIG{INT}= 'DEFAULT'; # If we get a ^C again, we die...
mtr_warning("got INT signal, cleaning up.....");
- stop_masters_slaves();
+ stop_all_servers();
mtr_error("We die from ^C signal from user");
}
@@ -1118,31 +1705,24 @@ sub kill_running_server () {
if ( $opt_fast or $glob_use_embedded_server )
{
# FIXME is embedded server really using PID files?!
- unlink($master->[0]->{'path_mypid'});
- unlink($master->[1]->{'path_mypid'});
- unlink($slave->[0]->{'path_mypid'});
- unlink($slave->[1]->{'path_mypid'});
- unlink($slave->[2]->{'path_mypid'});
+ unlink($master->[0]->{'path_pid'});
+ unlink($master->[1]->{'path_pid'});
+ unlink($slave->[0]->{'path_pid'});
+ unlink($slave->[1]->{'path_pid'});
+ unlink($slave->[2]->{'path_pid'});
}
else
{
# Ensure that no old mysqld test servers are running
# This is different from terminating processes we have
- # started from ths run of the script, this is terminating
+ # started from this run of the script, this is terminating
# leftovers from previous runs.
- mtr_report("Killing Possible Leftover Processes");
- mkpath("$opt_vardir/log"); # Needed for mysqladmin log
mtr_kill_leftovers();
-
- ndbcluster_stop();
- $master->[0]->{'ndbcluster'}= 1;
- }
+ }
}
-sub kill_and_cleanup () {
-
- kill_running_server ();
+sub cleanup_stale_files () {
mtr_report("Removing Stale Files");
@@ -1186,16 +1766,7 @@ sub kill_and_cleanup () {
mkpath("$opt_vardir/tmp");
mkpath($opt_tmpdir) if $opt_tmpdir ne "$opt_vardir/tmp";
- # FIXME do we really need to create these all, or are they
- # created for us when tables are created?
-
- my @data_dir_lst = (
- $master->[0]->{'path_myddir'},
- $master->[1]->{'path_myddir'},
- $slave->[0]->{'path_myddir'},
- $slave->[1]->{'path_myddir'},
- $slave->[2]->{'path_myddir'});
-
+ # Remove old and create new data dirs
foreach my $data_dir (@data_dir_lst)
{
rmtree("$data_dir");
@@ -1214,101 +1785,350 @@ sub kill_and_cleanup () {
mkpath("$opt_vardir/std_data_ln");
opendir(DIR, "$glob_mysql_test_dir/std_data")
or mtr_error("Can't find the std_data directory: $!");
- for my $elem ( readdir(DIR) ) {
- next if -d "$glob_mysql_test_dir/std_data/$elem";
- copy("$glob_mysql_test_dir/std_data/$elem", "$opt_vardir/std_data_ln/$elem");
+ for(readdir(DIR)) {
+ next if -d "$glob_mysql_test_dir/std_data/$_";
+ copy("$glob_mysql_test_dir/std_data/$_", "$opt_vardir/std_data_ln/$_");
}
closedir(DIR);
}
}
+sub check_running_as_root () {
+ # Check if running as root
+ # i.e a file can be read regardless what mode we set it to
+ my $test_file= "$opt_vardir/test_running_as_root.txt";
+ mtr_tofile($test_file, "MySQL");
+ chmod(oct("0000"), $test_file);
+
+ my $result="";
+ if (open(FILE,"<",$test_file))
+ {
+ $result= join('', <FILE>);
+ close FILE;
+ }
+
+ chmod(oct("0755"), $test_file);
+ unlink($test_file);
+
+ $ENV{'MYSQL_TEST_ROOT'}= "NO";
+ if ($result eq "MySQL")
+ {
+ mtr_warning("running this script as _root_ will cause some " .
+ "tests to be skipped");
+ $ENV{'MYSQL_TEST_ROOT'}= "YES";
+ }
+}
+
+
+sub check_ssl_support ($) {
+ my $mysqld_variables= shift;
+
+ if ($opt_skip_ssl || $opt_extern)
+ {
+ mtr_report("Skipping SSL");
+ $opt_ssl_supported= 0;
+ $opt_ssl= 0;
+ return;
+ }
+
+ if ( $mysqld_variables->{'ssl'} eq "FALSE" )
+ {
+ if ( $opt_ssl)
+ {
+ mtr_error("Couldn't find support for SSL");
+ return;
+ }
+ mtr_report("Skipping SSL, mysqld not compiled with SSL");
+ $opt_ssl_supported= 0;
+ $opt_ssl= 0;
+ return;
+ }
+ mtr_report("Setting mysqld to support SSL connections");
+ $opt_ssl_supported= 1;
+}
+
+
+sub check_debug_support ($) {
+ my $mysqld_variables= shift;
+
+ if ( $mysqld_variables->{'debug'} )
+ {
+ #mtr_report("Binaries are not debug compiled");
+ $debug_compiled_binaries= 0;
+
+ if ( $opt_debug )
+ {
+ mtr_error("Can't use --debug, binaries does not support it");
+ }
+ return;
+ }
+ mtr_report("Binaries are debug compiled");
+ $debug_compiled_binaries= 1;
+}
+
##############################################################################
#
# Start the ndb cluster
#
##############################################################################
-sub ndbcluster_support () {
+sub check_ndbcluster_support ($) {
+ my $mysqld_variables= shift;
- # check ndbcluster support by testing using a switch
- # that is only available in that case
- if ( mtr_run($exe_mysqld,
- ["--no-defaults",
- "--ndb-use-exact-count",
- "--help"],
- "", "/dev/null", "/dev/null", "") != 0 )
+ if ($opt_skip_ndbcluster)
{
- mtr_report("No ndbcluster support");
- return 0;
+ mtr_report("Skipping ndbcluster");
+ $opt_skip_ndbcluster_slave= 1;
+ return;
}
- mtr_report("Has ndbcluster support");
- return 1;
+
+ if ( $mysqld_variables->{'ndbcluster'} eq "FALSE")
+ {
+ mtr_report("Skipping ndbcluster, mysqld not compiled with ndbcluster");
+ $opt_skip_ndbcluster= 1;
+ $opt_skip_ndbcluster_slave= 1;
+ return;
+ }
+ $opt_ndbcluster_supported= 1;
+ mtr_report("Using ndbcluster when necessary, mysqld supports it");
+ return;
}
-# FIXME why is there a different start below?!
-sub ndbcluster_install () {
+sub ndbcluster_start_install ($) {
+ my $cluster= shift;
- if ( ! $opt_with_ndbcluster or $glob_use_running_ndbcluster )
+ if ( $opt_skip_ndbcluster or $glob_use_running_ndbcluster )
{
return 0;
}
- mtr_report("Install ndbcluster");
- my $ndbcluster_opts= $opt_bench ? "" : "--small";
- my $ndbcluster_port_base= $opt_ndbcluster_port + 2;
- if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
- ["--port=$opt_ndbcluster_port",
- "--port-base=$ndbcluster_port_base",
- "--data-dir=$opt_vardir",
- $ndbcluster_opts,
- "--initial"],
- "", "", "", "") )
- {
- mtr_error("Error ndbcluster_install");
- return 1;
+
+ mtr_report("Installing $cluster->{'name'} Cluster");
+
+ mkdir($cluster->{'data_dir'});
+
+ # Create a config file from template
+ my $ndb_no_ord=512;
+ my $ndb_no_attr=2048;
+ my $ndb_con_op=105000;
+ my $ndb_dmem="80M";
+ my $ndb_imem="24M";
+ my $ndb_pbmem="32M";
+ my $nodes= $cluster->{'nodes'};
+ my $ndb_host= "localhost";
+ my $ndb_diskless= 0;
+
+ if (!$opt_bench)
+ {
+ # Use a smaller configuration
+ $ndb_no_ord=32;
+ $ndb_con_op=5000;
+ $ndb_dmem="20M";
+ $ndb_imem="1M";
+ $ndb_pbmem="4M";
}
- ndbcluster_stop();
- $master->[0]->{'ndbcluster'}= 1;
+ my $config_file_template= "ndb/ndb_config_${nodes}_node.ini";
+ my $config_file= "$cluster->{'data_dir'}/config.ini";
+
+ open(IN, $config_file_template)
+ or mtr_error("Can't open $config_file_template: $!");
+ open(OUT, ">", $config_file)
+ or mtr_error("Can't write to $config_file: $!");
+ while (<IN>)
+ {
+ chomp;
+
+ s/CHOOSE_MaxNoOfAttributes/$ndb_no_attr/;
+ s/CHOOSE_MaxNoOfOrderedIndexes/$ndb_no_ord/;
+ s/CHOOSE_MaxNoOfConcurrentOperations/$ndb_con_op/;
+ s/CHOOSE_DataMemory/$ndb_dmem/;
+ s/CHOOSE_IndexMemory/$ndb_imem/;
+ s/CHOOSE_Diskless/$ndb_diskless/;
+ s/CHOOSE_HOSTNAME_.*/$ndb_host/;
+ s/CHOOSE_FILESYSTEM/$cluster->{'data_dir'}/;
+ s/CHOOSE_PORT_MGM/$cluster->{'port'}/;
+ s/CHOOSE_DiskPageBufferMemory/$ndb_pbmem/;
+
+ print OUT "$_ \n";
+ }
+ close OUT;
+ close IN;
+
+
+ # Start cluster with "--initial"
+
+ ndbcluster_start($cluster, "--initial");
return 0;
}
-sub ndbcluster_start () {
- if ( ! $opt_with_ndbcluster or $glob_use_running_ndbcluster )
+sub ndbcluster_wait_started($$){
+ my $cluster= shift;
+ my $ndb_waiter_extra_opt= shift;
+ my $path_waiter_log= "$cluster->{'data_dir'}/ndb_waiter.log";
+ my $args;
+
+ mtr_init_args(\$args);
+
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--ndb-connectstring=%s", $cluster->{'connect_string'});
+ mtr_add_arg($args, "--timeout=60");
+
+ if ($ndb_waiter_extra_opt)
+ {
+ mtr_add_arg($args, "$ndb_waiter_extra_opt");
+ }
+
+ # 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
+ my $res= mtr_run($exe_ndb_waiter, $args,
+ "", $path_waiter_log, $path_waiter_log, "");
+ mtr_verbose("ndbcluster_wait_started, returns: $res") if $res;
+ return $res;
+}
+
+
+
+sub mysqld_wait_started($){
+ my $mysqld= shift;
+
+ my $res= sleep_until_file_created($mysqld->{'path_pid'},
+ $mysqld->{'start_timeout'},
+ $mysqld->{'pid'});
+ return $res == 0;
+}
+
+
+sub ndb_mgmd_wait_started($) {
+ my ($cluster)= @_;
+
+ my $retries= 100;
+ while (ndbcluster_wait_started($cluster, "--no-contact") and
+ $retries)
+ {
+ # Millisceond sleep emulated with select
+ select(undef, undef, undef, (0.1));
+
+ $retries--;
+ }
+
+ return $retries == 0;
+
+}
+
+sub ndb_mgmd_start ($) {
+ my $cluster= shift;
+
+ my $args; # Arg vector
+ my $pid= -1;
+
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--nodaemon");
+ mtr_add_arg($args, "--config-file=%s", "$cluster->{'data_dir'}/config.ini");
+
+
+ my $path_ndb_mgmd_log= "$cluster->{'data_dir'}/\l$cluster->{'name'}_ndb_mgmd.log";
+ $pid= mtr_spawn($exe_ndb_mgmd, $args, "",
+ $path_ndb_mgmd_log,
+ $path_ndb_mgmd_log,
+ "",
+ { append_log_file => 1 });
+
+ # FIXME Should not be needed
+ # Unfortunately the cluster nodes will fail to start
+ # if ndb_mgmd has not started properly
+ if (ndb_mgmd_wait_started($cluster))
+ {
+ mtr_error("Failed to wait for start of ndb_mgmd");
+ }
+
+ # Remember pid of ndb_mgmd
+ $cluster->{'pid'}= $pid;
+
+ mtr_verbose("ndb_mgmd_start, pid: $pid");
+
+ return $pid;
+}
+
+
+sub ndbd_start ($$$) {
+ my $cluster= shift;
+ my $idx= shift;
+ my $extra_args= shift;
+
+ my $args; # Arg vector
+ my $pid= -1;
+
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--ndb-connectstring=%s", "$cluster->{'connect_string'}");
+ mtr_add_arg($args, "--character-sets-dir=%s", "$path_charsetsdir");
+ mtr_add_arg($args, "--nodaemon");
+ mtr_add_arg($args, "$extra_args");
+
+ my $nodeid= $cluster->{'ndbds'}->[$idx]->{'nodeid'};
+ my $path_ndbd_log= "$cluster->{'data_dir'}/ndb_${nodeid}.log";
+ $pid= mtr_spawn($exe_ndbd, $args, "",
+ $path_ndbd_log,
+ $path_ndbd_log,
+ "",
+ { append_log_file => 1 });
+
+ # Add pid to list of pids for this cluster
+ $cluster->{'ndbds'}->[$idx]->{'pid'}= $pid;
+
+ # Rememeber options used when starting
+ $cluster->{'ndbds'}->[$idx]->{'start_extra_args'}= $extra_args;
+ $cluster->{'ndbds'}->[$idx]->{'idx'}= $idx;
+
+ mtr_verbose("ndbd_start, pid: $pid");
+
+ return $pid;
+}
+
+
+sub ndbcluster_start ($$) {
+ my $cluster= shift;
+ my $extra_args= shift;
+
+ mtr_verbose("ndbcluster_start '$cluster->{'name'}'");
+
+ if ( $glob_use_running_ndbcluster )
{
return 0;
}
- # FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
- if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
- ["--port=$opt_ndbcluster_port",
- "--data-dir=$opt_vardir"],
- "", "/dev/null", "", "") )
+
+ if ( $cluster->{'pid'} )
{
- mtr_error("Error ndbcluster_start");
- return 1;
+ mtr_error("Cluster '$cluster->{'name'}' already started");
+ }
+
+ ndb_mgmd_start($cluster);
+
+ for ( my $idx= 0; $idx < $cluster->{'nodes'}; $idx++ )
+ {
+ ndbd_start($cluster, $idx, $extra_args);
}
return 0;
}
-sub ndbcluster_stop () {
- if ( ! $opt_with_ndbcluster or $glob_use_running_ndbcluster )
+sub rm_ndbcluster_tables ($) {
+ my $dir= shift;
+ foreach my $bin ( glob("$dir/cluster/apply_status*"),
+ glob("$dir/cluster/schema*") )
{
- return;
+ unlink($bin);
}
- my $ndbcluster_port_base= $opt_ndbcluster_port + 2;
- # FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
- mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
- ["--port=$opt_ndbcluster_port",
- "--data-dir=$opt_vardir",
- "--stop"],
- "", "/dev/null", "", "");
-
- return;
}
@@ -1323,9 +2143,9 @@ sub run_benchmarks ($) {
my $args;
- if ( ! $glob_use_embedded_server and ! $opt_local_master )
+ if ( ! $glob_use_embedded_server )
{
- $master->[0]->{'pid'}= mysqld_start('master',0,[],[]);
+ mysqld_start($master->[0],[],[]);
if ( ! $master->[0]->{'pid'} )
{
mtr_error("Can't start the mysqld server");
@@ -1334,7 +2154,7 @@ sub run_benchmarks ($) {
mtr_init_args(\$args);
- mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
+ mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'});
mtr_add_arg($args, "--user=%s", $opt_user);
if ( $opt_small_bench )
@@ -1348,10 +2168,8 @@ sub run_benchmarks ($) {
mtr_add_arg($args, "--create-options=TYPE=ndb");
}
- my $benchdir= "$glob_basedir/sql-bench";
- chdir($benchdir); # FIXME check error
-
- # FIXME write shorter....
+ chdir($glob_mysql_bench_dir)
+ or mtr_error("Couldn't chdir to '$glob_mysql_bench_dir': $!");
if ( ! $benchmark )
{
@@ -1384,29 +2202,26 @@ sub run_benchmarks ($) {
#
##############################################################################
-# FIXME how to specify several suites to run? Comma separated list?
-
-sub run_tests () {
- run_suite($opt_suite);
-}
-
sub run_suite () {
- my $suite= shift;
+ my ($suite, $tests)= @_;
mtr_print_thick_line();
- mtr_report("Finding Tests in the '$suite' suite");
-
mtr_timer_start($glob_timers,"suite", 60 * $opt_suite_timeout);
- my $tests= collect_test_cases($suite);
-
mtr_report("Starting Tests in the '$suite' suite");
+ mtr_report_tests_not_skipped_though_disabled($tests);
+
mtr_print_header();
foreach my $tinfo ( @$tests )
{
+ if (run_testcase_check_skip_test($tinfo))
+ {
+ next;
+ }
+
mtr_timer_start($glob_timers,"testcase", 60 * $opt_testcase_timeout);
run_testcase($tinfo);
mtr_timer_stop($glob_timers,"testcase");
@@ -1414,10 +2229,11 @@ sub run_suite () {
mtr_print_line();
- if ( ! $opt_gdb and ! $glob_use_running_server and
- ! $opt_ddd and ! $glob_use_embedded_server )
+ if ( ! $glob_debugger and
+ ! $glob_use_running_server and
+ ! $glob_use_embedded_server )
{
- stop_masters_slaves();
+ stop_all_servers();
}
if ( $opt_gcov )
@@ -1431,6 +2247,8 @@ sub run_suite () {
mtr_report_stats($tests);
+# Look for testname.warning files if --do-test=
+
mtr_timer_stop($glob_timers,"suite");
}
@@ -1441,26 +2259,99 @@ sub run_suite () {
#
##############################################################################
+sub initialize_servers () {
+ if ( ! $glob_use_running_server )
+ {
+ kill_running_server();
+
+ unless ( $opt_start_dirty )
+ {
+ cleanup_stale_files();
+ mysql_install_db();
+ if ( $opt_force )
+ {
+ save_installed_db();
+ }
+ }
+ check_running_as_root();
+ }
+}
+
sub mysql_install_db () {
- # FIXME not exactly true I think, needs improvements
install_db('master', $master->[0]->{'path_myddir'});
- install_db('master', $master->[1]->{'path_myddir'});
- install_db('slave', $slave->[0]->{'path_myddir'});
- install_db('slave', $slave->[1]->{'path_myddir'});
- install_db('slave', $slave->[2]->{'path_myddir'});
- if ( ndbcluster_install() )
+ # FIXME check if testcase really is using second master
+ copy_install_db('master', $master->[1]->{'path_myddir'});
+
+ # Install the number of slave databses needed
+ for (my $idx= 0; $idx < $max_slave_num; $idx++)
{
- # failed to install, disable usage but flag that its no ok
- $opt_with_ndbcluster= 0;
- $flag_ndb_status_ok= 0;
+ copy_install_db("slave".($idx+1), $slave->[$idx]->{'path_myddir'});
}
+ if ( ! $opt_skip_im )
+ {
+ im_prepare_env($instance_manager);
+ }
+
+ my $cluster_started_ok= 1; # Assume it can be started
+
+ if (ndbcluster_start_install($clusters->[0]) ||
+ $max_slave_num && ndbcluster_start_install($clusters->[1]))
+ {
+ mtr_warning("Failed to start install of cluster");
+ $cluster_started_ok= 0;
+ }
+
+ foreach my $cluster (@{$clusters})
+ {
+
+ next if !$cluster->{'pid'};
+
+ $cluster->{'installed_ok'}= 1; # Assume install suceeds
+
+ if (ndbcluster_wait_started($cluster, ""))
+ {
+ # failed to install, disable usage and flag that its no ok
+ mtr_report("ndbcluster_install of $cluster->{'name'} failed");
+ $cluster->{"installed_ok"}= 0;
+
+ $cluster_started_ok= 0;
+ }
+ }
+
+ if ( ! $cluster_started_ok )
+ {
+ if ( $opt_force)
+ {
+ # Continue without cluster
+ }
+ else
+ {
+ mtr_error("To continue, re-run with '--force'.");
+ }
+ }
+
+ # Stop clusters...
+ stop_all_servers();
+
return 0;
}
+sub copy_install_db ($$) {
+ my $type= shift;
+ my $data_dir= shift;
+
+ mtr_report("Installing \u$type Database");
+
+ # Just copy the installed db from first master
+ mtr_copy_dir($master->[0]->{'path_myddir'}, $data_dir);
+
+}
+
+
sub install_db ($$) {
my $type= shift;
my $data_dir= shift;
@@ -1469,7 +2360,7 @@ sub install_db ($$) {
my $init_db_sql_tmp= "/tmp/init_db.sql$$";
my $args;
- mtr_report("Installing \u$type Databases");
+ mtr_report("Installing \u$type Database");
open(IN, $init_db_sql)
or mtr_error("Can't open $init_db_sql: $!");
@@ -1505,16 +2396,29 @@ sub install_db ($$) {
mtr_add_arg($args, "--datadir=%s", $data_dir);
mtr_add_arg($args, "--skip-innodb");
mtr_add_arg($args, "--skip-ndbcluster");
- mtr_add_arg($args, "--skip-bdb");
+ mtr_add_arg($args, "--tmpdir=.");
- if ( ! $opt_netware )
+ if ( $opt_debug )
+ {
+ mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap_%s.trace",
+ $path_vardir_trace, $type);
+ }
+
+ if ( ! $glob_netware )
{
mtr_add_arg($args, "--language=%s", $path_language);
mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
}
+ # Log bootstrap command
+ my $path_bootstrap_log= "$opt_vardir/log/bootstrap.log";
+ mtr_tofile($path_bootstrap_log,
+ "$exe_mysqld " . join(" ", @$args) . "\n");
+
if ( mtr_run($exe_mysqld, $args, $init_db_sql_tmp,
- $path_manager_log, $path_manager_log, "") != 0 )
+ $path_bootstrap_log, $path_bootstrap_log,
+ "", { append_log_file => 1 }) != 0 )
+
{
unlink($init_db_sql_tmp);
mtr_error("Error executing mysqld --bootstrap\n" .
@@ -1524,31 +2428,121 @@ sub install_db ($$) {
}
-##############################################################################
-#
-# Run a single test case
-#
-##############################################################################
+sub im_prepare_env($) {
+ my $instance_manager = shift;
-# When we get here, we have already filtered out test cases that doesn't
-# apply to the current setup, for example if we use a running server, test
-# cases that restart the server are dropped. So this function should mostly
-# be about doing things, not a lot of logic.
+ im_create_passwd_file($instance_manager);
+ im_prepare_data_dir($instance_manager);
+}
-# We don't start and kill the servers for each testcase. But some
-# testcases needs a restart, because they specify options to start
-# mysqld with. After that testcase, we need to restart again, to set
-# back the normal options.
-sub run_testcase ($) {
- my $tinfo= shift;
+sub im_create_passwd_file($) {
+ my $instance_manager = shift;
- my $tname= $tinfo->{'name'};
+ my $pwd_file_path = $instance_manager->{'password_file'};
- mtr_tonewfile($opt_current_test,"$tname\n"); # Always tell where we are
+ mtr_report("Creating IM password file ($pwd_file_path)");
- # output current test to ndbcluster log file to enable diagnostics
- mtr_tofile($file_ndb_testrun_log,"CURRENT TEST $tname\n");
+ open(OUT, ">", $pwd_file_path)
+ or mtr_error("Can't write to $pwd_file_path: $!");
+
+ print OUT $instance_manager->{'admin_login'}, ":",
+ $instance_manager->{'admin_sha1'}, "\n";
+
+ close(OUT);
+}
+
+
+sub im_create_defaults_file($) {
+ my $instance_manager = shift;
+
+ my $defaults_file = $instance_manager->{'defaults_file'};
+
+ open(OUT, ">", $defaults_file)
+ or mtr_error("Can't write to $defaults_file: $!");
+
+ print OUT <<EOF
+[mysql]
+
+[manager]
+pid-file = $instance_manager->{path_pid}
+angel-pid-file = $instance_manager->{path_angel_pid}
+socket = $instance_manager->{path_sock}
+port = $instance_manager->{port}
+password-file = $instance_manager->{password_file}
+default-mysqld-path = $exe_mysqld
+
+EOF
+;
+
+ foreach my $instance (@{$instance_manager->{'instances'}})
+ {
+ my $server_id = $instance->{'server_id'};
+
+ print OUT <<EOF
+[mysqld$server_id]
+socket = $instance->{path_sock}
+pid-file = $instance->{path_pid}
+port = $instance->{port}
+datadir = $instance->{path_datadir}
+log = $instance->{path_datadir}/mysqld$server_id.log
+log-error = $instance->{path_datadir}/mysqld$server_id.err.log
+log-slow-queries = $instance->{path_datadir}/mysqld$server_id.slow.log
+language = $path_language
+character-sets-dir = $path_charsetsdir
+basedir = $path_my_basedir
+server_id = $server_id
+skip-stack-trace
+skip-innodb
+skip-ndbcluster
+EOF
+;
+
+ print OUT "nonguarded\n" if $instance->{'nonguarded'};
+ print OUT "log-output=FILE\n" if $instance->{'old_log_format'};
+ print OUT "\n";
+ }
+
+ close(OUT);
+}
+
+
+sub im_prepare_data_dir($) {
+ my $instance_manager = shift;
+
+ foreach my $instance (@{$instance_manager->{'instances'}})
+ {
+ copy_install_db(
+ 'im_mysqld_' . $instance->{'server_id'},
+ $instance->{'path_datadir'});
+ }
+}
+
+
+
+#
+# Restore snapshot of the installed slave databases
+# if the snapshot exists
+#
+sub restore_slave_databases ($) {
+ my ($num_slaves)= @_;
+
+ if ( -d $path_snapshot)
+ {
+ for (my $idx= 0; $idx < $num_slaves; $idx++)
+ {
+ my $data_dir= $slave->[$idx]->{'path_myddir'};
+ my $name= basename($data_dir);
+ rmtree($data_dir);
+ mtr_copy_dir("$path_snapshot/$name", $data_dir);
+ }
+ }
+}
+
+
+sub run_testcase_check_skip_test($)
+{
+ my ($tinfo)= @_;
# ----------------------------------------------------------------------
# If marked to skip, just print out and return.
@@ -1561,213 +2555,116 @@ sub run_testcase ($) {
{
mtr_report_test_name($tinfo);
mtr_report_test_skipped($tinfo);
- return;
+ return 1;
}
- # ----------------------------------------------------------------------
- # If not using a running servers we may need to stop and restart.
- # We restart in the case we have initiation scripts, server options
- # etc to run. But we also restart again after the test first restart
- # and test is run, to get back to normal server settings.
- #
- # To make the code a bit more clean, we actually only stop servers
- # here, and mark this to be done. Then a generic "start" part will
- # start up the needed servers again.
- # ----------------------------------------------------------------------
-
- if ( ! $glob_use_running_server and ! $glob_use_embedded_server )
+ # If test needs cluster, check that master installed ok
+ if ( $tinfo->{'ndb_test'} and !$clusters->[0]->{'installed_ok'} )
{
- # We try to find out if we are to restart the server
- my $do_restart= 0; # Assumes we don't have to
+ mtr_report_test_name($tinfo);
+ mtr_report_test_failed($tinfo);
+ return 1;
+ }
- if ( $tinfo->{'master_sh'} )
- {
- $do_restart= 1; # Always restart if script to run
- }
- elsif ( $tinfo->{'ndb_test'} and $master->[0]->{'ndbcluster'} == 1 )
- {
- $do_restart= 1; # Restart with cluster
- # print "Restarting because cluster need to be enabled\n";
- }
- elsif ($tinfo->{'ndb_test'} == 0 and $master->[0]->{'ndbcluster'} == 0)
- {
- $do_restart= 1; # Restart without cluster
- # print "Restarting because cluster need to be disabled\n";
- }
- elsif ( $master->[0]->{'running_master_is_special'} and
- $master->[0]->{'running_master_is_special'}->{'timezone'} eq
- $tinfo->{'timezone'} and
- mtr_same_opts($master->[0]->{'running_master_is_special'}->{'master_opt'},
- $tinfo->{'master_opt'}) )
- {
- # If running master was started with special settings, but
- # the current test requuires the same ones, we *don't* restart.
- $do_restart= 0;
- }
- elsif ( $tinfo->{'master_restart'} or
- $master->[0]->{'running_master_is_special'} )
- {
- $do_restart= 1;
- }
+ # If test needs slave cluster, check that it installed ok
+ if ( $tinfo->{'ndb_test'} and $tinfo->{'slave_num'} and
+ !$clusters->[1]->{'installed_ok'} )
+ {
+ mtr_report_test_name($tinfo);
+ mtr_report_test_failed($tinfo);
+ return 1;
+ }
- if ( $do_restart )
- {
- stop_masters();
- delete $master->[0]->{'running_master_is_special'}; # Forget history
- }
+ return 0;
+}
- # ----------------------------------------------------------------------
- # Always terminate all slaves, if any. Else we may have useless
- # reconnection attempts and error messages in case the slave and
- # master servers restart.
- # ----------------------------------------------------------------------
- stop_slaves();
- }
+sub do_before_run_mysqltest($)
+{
+ my $tinfo= shift;
+ my $tname= $tinfo->{'name'};
- # ----------------------------------------------------------------------
- # Prepare to start masters. Even if we use embedded, we want to run
- # the preparation.
- # ----------------------------------------------------------------------
+ # Remove old reject file
+ if ( $opt_suite eq "main" )
+ {
+ unlink("r/$tname.reject");
+ }
+ else
+ {
+ unlink("suite/$opt_suite/r/$tname.reject");
+ }
- $ENV{'TZ'}= $tinfo->{'timezone'};
+ mtr_tonewfile($path_current_test_log,"$tname\n"); # Always tell where we are
- mtr_report_test_name($tinfo);
+ # output current test to ndbcluster log file to enable diagnostics
+ mtr_tofile($path_ndb_testrun_log,"CURRENT TEST $tname\n");
mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n");
-
-# FIXME test cases that depend on each other, prevent this from
-# being at this location.
-# do_before_start_master($tname,$tinfo->{'master_sh'});
-
- # ----------------------------------------------------------------------
- # If any mysqld servers running died, we have to know
- # ----------------------------------------------------------------------
-
- mtr_record_dead_children();
-
- # ----------------------------------------------------------------------
- # Start masters
- # ----------------------------------------------------------------------
-
- if ( ! $glob_use_running_server and ! $glob_use_embedded_server )
+ if ( $master->[1]->{'pid'} )
{
- # FIXME give the args to the embedded server?!
- # FIXME what does $opt_local_master mean?!
- # FIXME split up start and check that started so that can do
- # starts in parallel, masters and slaves at the same time.
-
- if ( ! $opt_local_master )
- {
- if ( $master->[0]->{'ndbcluster'} && $tinfo->{'ndb_test'})
- {
- $master->[0]->{'ndbcluster'}= ndbcluster_start();
- if ( $master->[0]->{'ndbcluster'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
- if ( ! $master->[0]->{'pid'} )
- {
- # FIXME not correct location for do_before_start_master()
- do_before_start_master($tname,$tinfo->{'master_sh'});
+ mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+ }
+}
- # Save skip_ndbcluster
- my $save_opt_skip_ndbcluster= $opt_skip_ndbcluster;
- if (!$tinfo->{'ndb_test'})
- {
- # Modify skip_ndbcluster so cluster is skipped for this
- # and subsequent testcases(until we find one that does not cluster)
- $opt_skip_ndbcluster= 1;
- }
+sub do_after_run_mysqltest($)
+{
+ my $tinfo= shift;
+ my $tname= $tinfo->{'name'};
- $master->[0]->{'pid'}=
- mysqld_start('master',0,$tinfo->{'master_opt'},[]);
+ # Save info from this testcase run to mysqltest.log
+ mtr_appendfile_to_file($path_timefile, $path_mysqltest_log)
+ if -f $path_timefile;
+ mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n");
+}
- # Restore skip_ndbcluster
- $opt_skip_ndbcluster= $save_opt_skip_ndbcluster;
- if ( ! $master->[0]->{'pid'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
- if ( $opt_with_ndbcluster and ! $master->[1]->{'pid'} )
- {
- # Test needs cluster, start an extra mysqld connected to cluster
- $master->[1]->{'pid'}=
- mysqld_start('master',1,$tinfo->{'master_opt'},[]);
- if ( ! $master->[1]->{'pid'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
+##############################################################################
+#
+# Run a single test case
+#
+##############################################################################
- if ( $tinfo->{'master_restart'} )
- {
- # Save this test case information, so next can examine it
- $master->[0]->{'running_master_is_special'}= $tinfo;
- }
- }
+# When we get here, we have already filtered out test cases that doesn't
+# apply to the current setup, for example if we use a running server, test
+# cases that restart the server are dropped. So this function should mostly
+# be about doing things, not a lot of logic.
- # ----------------------------------------------------------------------
- # Start slaves - if needed
- # ----------------------------------------------------------------------
+# We don't start and kill the servers for each testcase. But some
+# testcases needs a restart, because they specify options to start
+# mysqld with. After that testcase, we need to restart again, to set
+# back the normal options.
- if ( $tinfo->{'slave_num'} )
- {
- mtr_tofile($slave->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+sub run_testcase ($) {
+ my $tinfo= shift;
- do_before_start_slave($tname,$tinfo->{'slave_sh'});
+ my $master_restart= run_testcase_need_master_restart($tinfo);
+ my $slave_restart= run_testcase_need_slave_restart($tinfo);
- for ( my $idx= 0; $idx < $tinfo->{'slave_num'}; $idx++ )
- {
- if ( ! $slave->[$idx]->{'pid'} )
- {
- $slave->[$idx]->{'pid'}=
- mysqld_start('slave',$idx,
- $tinfo->{'slave_opt'}, $tinfo->{'slave_mi'});
- if ( ! $slave->[$idx]->{'pid'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
- }
- }
+ if ($master_restart or $slave_restart)
+ {
+ run_testcase_stop_servers($tinfo, $master_restart, $slave_restart);
+ }
+ my $died= mtr_record_dead_children();
+ if ($died or $master_restart or $slave_restart)
+ {
+ run_testcase_start_servers($tinfo);
}
# ----------------------------------------------------------------------
- # If --start-and-exit given, stop here to let user manually run tests
+ # If --start-and-exit or --start-dirty given, stop here to let user manually
+ # run tests
# ----------------------------------------------------------------------
-
- if ( $opt_start_and_exit )
+ if ( $opt_start_and_exit or $opt_start_dirty )
{
mtr_report("\nServers started, exiting");
exit(0);
}
- # ----------------------------------------------------------------------
- # Run the test case
- # ----------------------------------------------------------------------
-
{
- # remove the old reject file
- if ( $opt_suite eq "main" )
- {
- unlink("r/$tname.reject");
- }
- else
- {
- unlink("suite/$opt_suite/r/$tname.reject");
- }
- unlink($path_timefile);
+ do_before_run_mysqltest($tinfo);
my $res= run_mysqltest($tinfo);
-
+ mtr_report_test_name($tinfo);
if ( $res == 0 )
{
mtr_report_test_passed($tinfo);
@@ -1775,6 +2672,12 @@ sub run_testcase ($) {
elsif ( $res == 62 )
{
# Testcase itself tell us to skip this one
+
+ # Try to get reason from mysqltest.log
+ my $last_line= mtr_lastlinefromfile($path_timefile) if -f $path_timefile;
+ my $reason= mtr_match_prefix($last_line, "reason: ");
+ $tinfo->{'comment'}=
+ defined $reason ? $reason : "Detected by testcase(reason unknown) ";
mtr_report_test_skipped($tinfo);
}
elsif ( $res == 63 )
@@ -1791,38 +2694,128 @@ sub run_testcase ($) {
"mysqltest returned unexpected code $res, " .
"it has probably crashed");
}
+
report_failure_and_restart($tinfo);
}
+
+ do_after_run_mysqltest($tinfo);
+ }
+
+ # ----------------------------------------------------------------------
+ # Stop Instance Manager if we are processing an IM-test case.
+ # ----------------------------------------------------------------------
+
+ if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' )
+ {
+ unless ( mtr_im_stop($instance_manager, $tinfo->{'name'}) )
+ {
+ mtr_error("Failed to stop Instance Manager.")
+ }
}
}
+#
+# Save a snapshot of the installed test db(s)
+# I.e take a snapshot of the var/ dir
+#
+sub save_installed_db () {
+
+ mtr_report("Saving snapshot of installed databases");
+ rmtree($path_snapshot);
+
+ foreach my $data_dir (@data_dir_lst)
+ {
+ my $name= basename($data_dir);
+ mtr_copy_dir("$data_dir", "$path_snapshot/$name");
+ }
+}
+
+
+#
+# Save any interesting files in the data_dir
+# before the data dir is removed.
+#
+sub save_files_before_restore($$) {
+ my $test_name= shift;
+ my $data_dir= shift;
+ my $save_name= "$opt_vardir/log/$test_name";
+
+ # Look for core files
+ foreach my $core_file ( glob("$data_dir/core*") )
+ {
+ my $core_name= basename($core_file);
+ mtr_report("Saving $core_name");
+ mkdir($save_name) if ! -d $save_name;
+ rename("$core_file", "$save_name/$core_name");
+ }
+}
+
+
+#
+# Restore snapshot of the installed test db(s)
+# if the snapshot exists
+#
+sub restore_installed_db ($) {
+ my $test_name= shift;
+
+ if ( -d $path_snapshot)
+ {
+ mtr_report("Restoring snapshot of databases");
+
+ foreach my $data_dir (@data_dir_lst)
+ {
+ my $name= basename($data_dir);
+ save_files_before_restore($test_name, $data_dir);
+ rmtree("$data_dir");
+ mtr_copy_dir("$path_snapshot/$name", "$data_dir");
+ }
+
+ # Remove the ndb_*_fs dirs for all ndbd nodes
+ # forcing a clean start of ndb
+ foreach my $cluster (@{$clusters})
+ {
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ rmtree("$ndbd->{'path_fs'}" );
+ }
+ }
+ }
+ else
+ {
+ # No snapshot existed
+ mtr_error("No snapshot existed");
+ }
+}
+
sub report_failure_and_restart ($) {
my $tinfo= shift;
mtr_report_test_failed($tinfo);
mtr_show_failed_diff($tinfo->{'name'});
print "\n";
- if ( ! $opt_force )
+ if ( $opt_force )
{
- my $test_mode= join(" ", @::glob_test_mode) || "default";
- print "Aborting: $tinfo->{'name'} failed in $test_mode mode. ";
- print "To continue, re-run with '--force'.\n";
- if ( ! $opt_gdb and ! $glob_use_running_server and
- ! $opt_ddd and ! $glob_use_embedded_server )
- {
- stop_masters_slaves();
- }
- mtr_exit(1);
+ # Stop all servers that are known to be running
+ stop_all_servers();
+
+ # Restore the snapshot of the installed test db
+ restore_installed_db($tinfo->{'name'});
+ print "Resuming Tests\n\n";
+ return;
}
- # FIXME always terminate on failure?!
- if ( ! $opt_gdb and ! $glob_use_running_server and
- ! $opt_ddd and ! $glob_use_embedded_server )
+ my $test_mode= join(" ", @::glob_test_mode) || "default";
+ print "Aborting: $tinfo->{'name'} failed in $test_mode mode. ";
+ print "To continue, re-run with '--force'.\n";
+ if ( ! $glob_debugger and
+ ! $glob_use_running_server and
+ ! $glob_use_embedded_server )
{
- stop_masters_slaves();
+ stop_all_servers();
}
- print "Resuming Tests\n\n";
+ mtr_exit(1);
+
}
@@ -1832,9 +2825,9 @@ sub report_failure_and_restart ($) {
#
##############################################################################
+
# The embedded server needs the cleanup so we do some of the start work
# but stop before actually running mysqld or anything.
-
sub do_before_start_master ($$) {
my $tname= shift;
my $init_script= shift;
@@ -1867,13 +2860,14 @@ sub do_before_start_master ($$) {
if ( $ret != 0 )
{
# FIXME rewrite those scripts to return 0 if successful
-# mtr_warning("$init_script exited with code $ret");
+ # mtr_warning("$init_script exited with code $ret");
}
}
# for gcov FIXME needed? If so we need more absolute paths
-# chdir($glob_basedir);
+ # chdir($glob_basedir);
}
+
sub do_before_start_slave ($$) {
my $tname= shift;
my $init_script= shift;
@@ -1901,7 +2895,7 @@ sub do_before_start_slave ($$) {
if ( $ret != 0 )
{
# FIXME rewrite those scripts to return 0 if successful
-# mtr_warning("$init_script exited with code $ret");
+ # mtr_warning("$init_script exited with code $ret");
}
}
@@ -1911,9 +2905,10 @@ sub do_before_start_slave ($$) {
}
}
+
sub mysqld_arguments ($$$$$) {
my $args= shift;
- my $type= shift; # master/slave/bootstrap
+ my $type= shift;
my $idx= shift;
my $extra_opt= shift;
my $slave_master_info= shift;
@@ -1921,7 +2916,7 @@ sub mysqld_arguments ($$$$$) {
my $sidx= ""; # Index as string, 0 is empty string
if ( $idx > 0 )
{
- $sidx= sprintf("%d", $idx); # sprintf not needed in Perl for this
+ $sidx= "$idx";
}
my $prefix= ""; # If mysqltest server arg
@@ -1937,15 +2932,19 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--console", $prefix);
mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir);
mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir);
- mtr_add_arg($args, "%s--core", $prefix);
+
+ if ( $mysql_version_id >= 50000 )
+ {
+ mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
+ }
+
mtr_add_arg($args, "%s--default-character-set=latin1", $prefix);
mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
- if ( defined $opt_valgrind_mysqld )
+ if ( $opt_valgrind_mysqld )
{
mtr_add_arg($args, "%s--skip-safemalloc", $prefix);
- mtr_add_arg($args, "%s--skip-bdb", $prefix);
}
my $pidfile;
@@ -1954,29 +2953,41 @@ sub mysqld_arguments ($$$$$) {
{
my $id= $idx > 0 ? $idx + 101 : 1;
- mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
- $opt_vardir, $sidx);
+ if (! $opt_skip_master_binlog)
+ {
+ mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
+ $opt_vardir, $sidx);
+ }
mtr_add_arg($args, "%s--pid-file=%s", $prefix,
- $master->[$idx]->{'path_mypid'});
+ $master->[$idx]->{'path_pid'});
mtr_add_arg($args, "%s--port=%d", $prefix,
- $master->[$idx]->{'path_myport'});
+ $master->[$idx]->{'port'});
mtr_add_arg($args, "%s--server-id=%d", $prefix, $id);
mtr_add_arg($args, "%s--socket=%s", $prefix,
- $master->[$idx]->{'path_mysock'});
- mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:50M", $prefix);
+ $master->[$idx]->{'path_sock'});
+ mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:10M:autoextend", $prefix);
mtr_add_arg($args, "%s--local-infile", $prefix);
mtr_add_arg($args, "%s--datadir=%s", $prefix,
$master->[$idx]->{'path_myddir'});
- if ( $idx > 0 )
+ if ( $idx > 0 or !$use_innodb)
{
mtr_add_arg($args, "%s--skip-innodb", $prefix);
}
- if ( $opt_skip_ndbcluster )
+ my $cluster= $clusters->[$master->[$idx]->{'cluster'}];
+ if ( $opt_skip_ndbcluster ||
+ !$cluster->{'pid'})
{
mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
}
+ else
+ {
+ mtr_add_arg($args, "%s--ndbcluster", $prefix);
+ mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
+ $cluster->{'connect_string'});
+ mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ }
}
if ( $type eq 'slave' )
@@ -1986,25 +2997,26 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--datadir=%s", $prefix,
$slave->[$idx]->{'path_myddir'});
- # FIXME slave get this option twice?!
- mtr_add_arg($args, "%s--exit-info=256", $prefix);
mtr_add_arg($args, "%s--init-rpl-role=slave", $prefix);
- mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix,
- $opt_vardir, $sidx); # FIXME use own dir for binlogs
- mtr_add_arg($args, "%s--log-slave-updates", $prefix);
- # FIXME option duplicated for slave
+ if (! $opt_skip_slave_binlog)
+ {
+ mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix,
+ $opt_vardir, $sidx); # FIXME use own dir for binlogs
+ mtr_add_arg($args, "%s--log-slave-updates", $prefix);
+ }
+
mtr_add_arg($args, "%s--log=%s", $prefix,
$slave->[$idx]->{'path_mylog'});
mtr_add_arg($args, "%s--master-retry-count=10", $prefix);
mtr_add_arg($args, "%s--pid-file=%s", $prefix,
- $slave->[$idx]->{'path_mypid'});
+ $slave->[$idx]->{'path_pid'});
mtr_add_arg($args, "%s--port=%d", $prefix,
- $slave->[$idx]->{'path_myport'});
+ $slave->[$idx]->{'port'});
mtr_add_arg($args, "%s--relay-log=%s/log/slave%s-relay-bin", $prefix,
$opt_vardir, $sidx);
mtr_add_arg($args, "%s--report-host=127.0.0.1", $prefix);
mtr_add_arg($args, "%s--report-port=%d", $prefix,
- $slave->[$idx]->{'path_myport'});
+ $slave->[$idx]->{'port'});
mtr_add_arg($args, "%s--report-user=root", $prefix);
mtr_add_arg($args, "%s--skip-innodb", $prefix);
mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
@@ -2014,9 +3026,9 @@ sub mysqld_arguments ($$$$$) {
# on the server. The path need to have constant length otherwise
# test results will vary, thus a relative path is used.
mtr_add_arg($args, "%s--slave-load-tmpdir=%s", $prefix,
- $path_slave_load_tmpdir);
+ "../tmp");
mtr_add_arg($args, "%s--socket=%s", $prefix,
- $slave->[$idx]->{'path_mysock'});
+ $slave->[$idx]->{'path_sock'});
mtr_add_arg($args, "%s--set-variable=slave_net_timeout=10", $prefix);
if ( @$slave_master_info )
@@ -2033,10 +3045,24 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--master-host=127.0.0.1", $prefix);
mtr_add_arg($args, "%s--master-password=", $prefix);
mtr_add_arg($args, "%s--master-port=%d", $prefix,
- $master->[0]->{'path_myport'}); # First master
+ $master->[0]->{'port'}); # First master
mtr_add_arg($args, "%s--server-id=%d", $prefix, $slave_server_id);
mtr_add_arg($args, "%s--rpl-recovery-rank=%d", $prefix, $slave_rpl_rank);
}
+
+ if ( $opt_skip_ndbcluster_slave ||
+ $slave->[$idx]->{'cluster'} == -1 ||
+ !$clusters->[$slave->[$idx]->{'cluster'}]->{'pid'} )
+ {
+ mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
+ }
+ else
+ {
+ mtr_add_arg($args, "%s--ndbcluster", $prefix);
+ mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
+ $clusters->[$slave->[$idx]->{'cluster'}]->{'connect_string'});
+ mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ }
} # end slave
if ( $opt_debug )
@@ -2044,28 +3070,21 @@ sub mysqld_arguments ($$$$$) {
if ( $type eq 'master' )
{
mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/master%s.trace",
- $prefix, $opt_vardir, $sidx);
+ $prefix, $path_vardir_trace, $sidx);
}
if ( $type eq 'slave' )
{
mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/slave%s.trace",
- $prefix, $opt_vardir, $sidx);
+ $prefix, $path_vardir_trace, $sidx);
}
}
- if ( $opt_with_ndbcluster && !$opt_skip_ndbcluster && $type eq 'master')
- {
- mtr_add_arg($args, "%s--ndbcluster", $prefix);
- mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
- $opt_ndbconnectstring);
- }
-
# FIXME always set nowdays??? SMALL_SERVER
mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
mtr_add_arg($args, "%s--sort_buffer=256K", $prefix);
mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix);
- if ( $opt_with_openssl )
+ if ( $opt_ssl_supported )
{
mtr_add_arg($args, "%s--ssl-ca=%s/std_data/cacert.pem", $prefix,
$glob_mysql_test_dir);
@@ -2080,7 +3099,8 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--log-warnings", $prefix);
}
- if ( $opt_gdb or $opt_client_gdb or $opt_manual_gdb or $opt_ddd)
+ # Indicate to "mysqld" it will be debugged in debugger
+ if ( $glob_debugger )
{
mtr_add_arg($args, "%s--gdb", $prefix);
}
@@ -2093,27 +3113,22 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--user=root", $prefix);
}
- if ( $type eq 'master' )
+ my $found_skip_core= 0;
+ foreach my $arg ( @opt_extra_mysqld_opt, @$extra_opt )
{
-
- if ( ! $opt_old_master )
+ # Allow --skip-core-file to be set in master.opt file
+ if ($arg eq "--skip-core-file")
{
- mtr_add_arg($args, "%s--rpl-recovery-rank=1", $prefix);
- mtr_add_arg($args, "%s--init-rpl-role=master", $prefix);
+ $found_skip_core= 1;
}
-
- # FIXME strange,.....
- # FIXME MYSQL_MYPORT is not set anythere?!
- if ( $opt_local_master )
+ else
{
- mtr_add_arg($args, "%s--host=127.0.0.1", $prefix);
- mtr_add_arg($args, "%s--port=%s", $prefix, $ENV{'MYSQL_MYPORT'});
+ mtr_add_arg($args, "%s%s", $prefix, $arg);
}
}
-
- foreach my $arg ( @opt_extra_mysqld_opt, @$extra_opt )
+ if ( !$found_skip_core )
{
- mtr_add_arg($args, "%s%s", $prefix, $arg);
+ mtr_add_arg($args, "%s%s", $prefix, "--core-file");
}
if ( $opt_bench )
@@ -2123,7 +3138,6 @@ sub mysqld_arguments ($$$$$) {
}
elsif ( $type eq 'master' )
{
- mtr_add_arg($args, "%s--exit-info=256", $prefix);
mtr_add_arg($args, "%s--open-files-limit=1024", $prefix);
mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'});
}
@@ -2131,14 +3145,6 @@ sub mysqld_arguments ($$$$$) {
return $args;
}
-# FIXME
-# if ( $type eq 'master' and $glob_use_embedded_server )
-# {
-# # Add a -A to each argument to pass it to embedded server
-# my @mysqltest_opt= map {("-A",$_)} @args;
-# $opt_extra_mysqltest_opt= \@mysqltest_opt;
-# return;
-# }
##############################################################################
#
@@ -2146,15 +3152,18 @@ sub mysqld_arguments ($$$$$) {
#
##############################################################################
-sub mysqld_start ($$$$) {
- my $type= shift; # master/slave/bootstrap
- my $idx= shift;
+sub mysqld_start ($$$) {
+ my $mysqld= shift;
my $extra_opt= shift;
my $slave_master_info= shift;
my $args; # Arg vector
my $exe;
- my $pid;
+ my $pid= -1;
+ my $wait_for_pid_file= 1;
+
+ my $type= $mysqld->{'type'};
+ my $idx= $mysqld->{'idx'};
if ( $type eq 'master' )
{
@@ -2166,214 +3175,682 @@ sub mysqld_start ($$$$) {
}
else
{
- $exe= $exe_mysqld;
+ mtr_error("Unknown 'type' \"$type\" passed to mysqld_start");
}
mtr_init_args(\$args);
- if ( defined $opt_valgrind_mysqld )
+ if ( $opt_valgrind_mysqld )
{
valgrind_arguments($args, \$exe);
}
mysqld_arguments($args,$type,$idx,$extra_opt,$slave_master_info);
- if ( $type eq 'master' )
+ if ( $opt_gdb || $opt_manual_gdb)
+ {
+ gdb_arguments(\$args, \$exe, "$type"."_$idx");
+ }
+ elsif ( $opt_ddd || $opt_manual_ddd )
+ {
+ ddd_arguments(\$args, \$exe, "$type"."_$idx");
+ }
+ elsif ( $opt_debugger )
+ {
+ debugger_arguments(\$args, \$exe, "$type"."_$idx");
+ }
+ elsif ( $opt_manual_debug )
+ {
+ print "\nStart $type in your debugger\n" .
+ "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;
+ }
+ else
+ {
+ # Default to not wait until pid file has been created
+ $wait_for_pid_file= 0;
+ }
+
+ if ($exe_libtool and $opt_valgrind)
{
- if ( $pid= mtr_spawn($exe, $args, "",
- $master->[$idx]->{'path_myerr'},
- $master->[$idx]->{'path_myerr'},
- "",
- { append_log_file => 1 }) )
+ # Add "libtool --mode-execute"
+ # if running in valgrind(to avoid valgrinding bash)
+ unshift(@$args, "--mode=execute", $exe);
+ $exe= $exe_libtool;
+ }
+
+
+ if ( defined $exe )
+ {
+ $pid= mtr_spawn($exe, $args, "",
+ $mysqld->{'path_myerr'},
+ $mysqld->{'path_myerr'},
+ "",
+ { append_log_file => 1 });
+ }
+
+
+ if ( $wait_for_pid_file && !sleep_until_file_created($mysqld->{'path_pid'},
+ $mysqld->{'start_timeout'},
+ $pid))
+ {
+
+ mtr_error("Failed to start mysqld $mysqld->{'type'}");
+ }
+
+
+ # Remember pid of the started process
+ $mysqld->{'pid'}= $pid;
+
+ # Remember options used when starting
+ $mysqld->{'start_opts'}= $extra_opt;
+ $mysqld->{'start_slave_master_info'}= $slave_master_info;
+
+ mtr_verbose("mysqld pid: $pid");
+ return $pid;
+}
+
+
+sub stop_all_servers () {
+
+ print "Stopping All Servers\n";
+
+ if ( ! $opt_skip_im )
+ {
+ print "Shutting-down Instance Manager\n";
+ unless (mtr_im_stop($instance_manager, "stop_all_servers"))
{
- return sleep_until_file_created($master->[$idx]->{'path_mypid'},
- $master->[$idx]->{'start_timeout'}, $pid);
+ mtr_error("Failed to stop Instance Manager.")
}
}
- if ( $type eq 'slave' )
+ my %admin_pids; # hash of admin processes that requests shutdown
+ my @kill_pids; # list of processes to shutdown/kill
+ my $pid;
+
+ # Start shutdown of all started masters
+ foreach my $mysqld (@{$master}, @{$slave})
{
- if ( $pid= mtr_spawn($exe, $args, "",
- $slave->[$idx]->{'path_myerr'},
- $slave->[$idx]->{'path_myerr'},
- "",
- { append_log_file => 1 }) )
+ if ( $mysqld->{'pid'} )
{
- return sleep_until_file_created($slave->[$idx]->{'path_mypid'},
- $master->[$idx]->{'start_timeout'}, $pid);
+ $pid= mtr_mysqladmin_start($mysqld, "shutdown", 70);
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $mysqld->{'pid'},
+ pidfile => $mysqld->{'path_pid'},
+ sockfile => $mysqld->{'path_sock'},
+ port => $mysqld->{'port'},
+ });
+
+ $mysqld->{'pid'}= 0; # Assume we are done with it
}
}
- return 0;
+ # Start shutdown of clusters
+ foreach my $cluster (@{$clusters})
+ {
+ if ( $cluster->{'pid'} )
+ {
+ $pid= mtr_ndbmgm_start($cluster, "shutdown");
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ if ( $ndbd->{'pid'} )
+ {
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0;
+ }
+ }
+ }
+ }
+
+ # Wait blocking until all shutdown processes has completed
+ mtr_wait_blocking(\%admin_pids);
+
+ # Make sure that process has shutdown else try to kill them
+ mtr_check_stop_servers(\@kill_pids);
+
+ foreach my $mysqld (@{$master}, @{$slave})
+ {
+ rm_ndbcluster_tables($mysqld->{'path_myddir'});
+ }
}
-sub stop_masters_slaves () {
- print "Ending Tests\n";
- print "Shutting-down MySQL daemon\n\n";
- stop_masters();
- print "Master(s) shutdown finished\n";
- stop_slaves();
- print "Slave(s) shutdown finished\n";
+sub run_testcase_need_master_restart($)
+{
+ my ($tinfo)= @_;
+
+ # We try to find out if we are to restart the master(s)
+ my $do_restart= 0; # Assumes we don't have to
+
+ if ( $tinfo->{'master_sh'} )
+ {
+ $do_restart= 1; # Always restart if script to run
+ mtr_verbose("Restart because: Always restart if script to run");
+ }
+ elsif ( ! $opt_skip_ndbcluster and
+ $tinfo->{'ndb_test'} == 0 and
+ $clusters->[0]->{'pid'} != 0 )
+ {
+ $do_restart= 1; # Restart without cluster
+ mtr_verbose("Restart because: Test does not need cluster");
+ }
+ elsif ( ! $opt_skip_ndbcluster and
+ $tinfo->{'ndb_test'} == 1 and
+ $clusters->[0]->{'pid'} == 0 )
+ {
+ $do_restart= 1; # Restart with cluster
+ mtr_verbose("Restart because: Test need cluster");
+ }
+ elsif ( $master->[0]->{'running_master_is_special'} and
+ $master->[0]->{'running_master_is_special'}->{'timezone'} eq
+ $tinfo->{'timezone'} and
+ mtr_same_opts($master->[0]->{'running_master_is_special'}->{'master_opt'},
+ $tinfo->{'master_opt'}) )
+ {
+ # If running master was started with special settings, but
+ # the current test requires the same ones, we *don't* restart.
+ $do_restart= 0;
+ mtr_verbose("Skip restart: options are equal " .
+ join(" ", @{$tinfo->{'master_opt'}}));
+ }
+ elsif ( $tinfo->{'master_restart'} )
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart because: master_restart");
+ }
+ elsif ( $master->[0]->{'running_master_is_special'} )
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart because: running_master_is_special");
+ }
+ # Check that running master was started with same options
+ # as the current test requires
+ elsif (! mtr_same_opts($master->[0]->{'start_opts'},
+ $tinfo->{'master_opt'}) )
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart because: running with different options '" .
+ join(" ", @{$tinfo->{'master_opt'}}) . "' != '" .
+ join(" ", @{$master->[0]->{'start_opts'}}) . "'" );
+ }
+
+ return $do_restart;
}
-sub stop_masters () {
+sub run_testcase_need_slave_restart($)
+{
+ my ($tinfo)= @_;
+
+ # We try to find out if we are to restart the slaves
+ my $do_slave_restart= 0; # Assumes we don't have to
+
+ # FIXME only restart slave when necessary
+ $do_slave_restart= 1;
+
+# if ( ! $slave->[0]->{'pid'} )
+# {
+# # mtr_verbose("Slave not started, no need to check slave restart");
+# }
+# elsif ( $do_restart )
+# {
+# $do_slave_restart= 1; # Always restart if master restart
+# mtr_verbose("Restart slave because: Master restart");
+# }
+# elsif ( $tinfo->{'slave_sh'} )
+# {
+# $do_slave_restart= 1; # Always restart if script to run
+# mtr_verbose("Restart slave because: Always restart if script to run");
+# }
+# elsif ( ! $opt_skip_ndbcluster_slave and
+# $tinfo->{'ndb_test'} == 0 and
+# $clusters->[1]->{'pid'} != 0 )
+# {
+# $do_slave_restart= 1; # Restart without slave cluster
+# mtr_verbose("Restart slave because: Test does not need slave cluster");
+# }
+# elsif ( ! $opt_with_ndbcluster_slave and
+# $tinfo->{'ndb_test'} == 1 and
+# $clusters->[1]->{'pid'} == 0 )
+# {
+# $do_slave_restart= 1; # Restart with slave cluster
+# mtr_verbose("Restart slave because: Test need slave cluster");
+# }
+# elsif ( $tinfo->{'slave_restart'} )
+# {
+# $do_slave_restart= 1;
+# mtr_verbose("Restart slave because: slave_restart");
+# }
+# elsif ( $slave->[0]->{'running_slave_is_special'} )
+# {
+# $do_slave_restart= 1;
+# mtr_verbose("Restart slave because: running_slave_is_special");
+# }
+# # Check that running slave was started with same options
+# # as the current test requires
+# elsif (! mtr_same_opts($slave->[0]->{'start_opts'},
+# $tinfo->{'slave_opt'}) )
+# {
+# $do_slave_restart= 1;
+# mtr_verbose("Restart slave because: running with different options '" .
+# join(" ", @{$tinfo->{'slave_opt'}}) . "' != '" .
+# join(" ", @{$slave->[0]->{'start_opts'}}) . "'" );
+# }
+
+ return $do_slave_restart;
- my @args;
+}
- for ( my $idx; $idx < 2; $idx++ )
+# ----------------------------------------------------------------------
+# If not using a running servers we may need to stop and restart.
+# We restart in the case we have initiation scripts, server options
+# etc to run. But we also restart again after the test first restart
+# and test is run, to get back to normal server settings.
+#
+# To make the code a bit more clean, we actually only stop servers
+# here, and mark this to be done. Then a generic "start" part will
+# start up the needed servers again.
+# ----------------------------------------------------------------------
+
+sub run_testcase_stop_servers($$$) {
+ my ($tinfo, $do_restart, $do_slave_restart)= @_;
+
+ if ( $glob_use_running_server || $glob_use_embedded_server )
{
- # FIXME if we hit ^C before fully started, this test will prevent
- # the mysqld process from being killed
- if ( $master->[$idx]->{'pid'} )
+ return;
+ }
+
+ my $pid;
+ my %admin_pids; # hash of admin processes that requests shutdown
+ my @kill_pids; # list of processes to shutdown/kill
+
+ # Remember if we restarted for this test case
+ $tinfo->{'restarted'}= $do_restart;
+
+ if ( $do_restart )
+ {
+ delete $master->[0]->{'running_master_is_special'}; # Forget history
+
+ # Start shutdown of all started masters
+ foreach my $mysqld (@{$master})
+ {
+ if ( $mysqld->{'pid'} )
+ {
+ $pid= mtr_mysqladmin_start($mysqld, "shutdown", 70);
+
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $mysqld->{'pid'},
+ pidfile => $mysqld->{'path_pid'},
+ sockfile => $mysqld->{'path_sock'},
+ port => $mysqld->{'port'},
+ });
+
+ $mysqld->{'pid'}= 0; # Assume we are done with it
+ }
+ }
+
+ # Start shutdown of master cluster
+ my $cluster= $clusters->[0];
+ if ( $cluster->{'pid'} )
{
- push(@args,{
- pid => $master->[$idx]->{'pid'},
- pidfile => $master->[$idx]->{'path_mypid'},
- sockfile => $master->[$idx]->{'path_mysock'},
- port => $master->[$idx]->{'path_myport'},
- });
- $master->[$idx]->{'pid'}= 0; # Assume we are done with it
+ $pid= mtr_ndbmgm_start($cluster, "shutdown");
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0; # Assume we are done with it
+ }
}
}
- if ( ! $master->[0]->{'ndbcluster'} )
+ if ( $do_restart || $do_slave_restart )
{
- ndbcluster_stop();
- $master->[0]->{'ndbcluster'}= 1;
- }
- mtr_stop_mysqld_servers(\@args);
-}
+ delete $slave->[0]->{'running_slave_is_special'}; # Forget history
-sub stop_slaves () {
- my $force= shift;
+ # Start shutdown of all started slaves
+ foreach my $mysqld (@{$slave})
+ {
+ if ( $mysqld->{'pid'} )
+ {
+ $pid= mtr_mysqladmin_start($mysqld, "shutdown", 70);
- my @args;
+ $admin_pids{$pid}= 1;
- for ( my $idx; $idx < 3; $idx++ )
- {
- if ( $slave->[$idx]->{'pid'} )
+ push(@kill_pids,{
+ pid => $mysqld->{'pid'},
+ pidfile => $mysqld->{'path_pid'},
+ sockfile => $mysqld->{'path_sock'},
+ port => $mysqld->{'port'},
+ });
+
+
+ $mysqld->{'pid'}= 0; # Assume we are done with it
+ }
+ }
+
+ # Start shutdown of slave cluster
+ my $cluster= $clusters->[1];
+ if ( $cluster->{'pid'} )
{
- push(@args,{
- pid => $slave->[$idx]->{'pid'},
- pidfile => $slave->[$idx]->{'path_mypid'},
- sockfile => $slave->[$idx]->{'path_mysock'},
- port => $slave->[$idx]->{'path_myport'},
- });
- $slave->[$idx]->{'pid'}= 0; # Assume we are done with it
+ $pid= mtr_ndbmgm_start($cluster, "shutdown");
+
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}} )
+ {
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0; # Assume we are done with it
+ }
}
}
- mtr_stop_mysqld_servers(\@args);
-}
+ # ----------------------------------------------------------------------
+ # Shutdown has now been started and lists for the shutdown processes
+ # and the processes to be killed has been created
+ # ----------------------------------------------------------------------
+ # Wait blocking until all shutdown processes has completed
+ mtr_wait_blocking(\%admin_pids);
-sub run_mysqltest ($) {
- my $tinfo= shift;
- my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} --password=";
- if ( $opt_debug )
+ # Make sure that process has shutdown else try to kill them
+ mtr_check_stop_servers(\@kill_pids);
+
+ foreach my $mysqld (@{$master}, @{$slave})
{
- $cmdline_mysqldump .=
- " --debug=d:t:A,$opt_vardir/log/mysqldump.trace";
+ if ( ! $mysqld->{'pid'} )
+ {
+ # Remove ndbcluster tables if server is stopped
+ rm_ndbcluster_tables($mysqld->{'path_myddir'});
+ }
}
- my $cmdline_mysqlimport= "$exe_mysqlimport -uroot " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} --password=";
- if ( $opt_debug )
+}
+
+sub run_testcase_start_servers($) {
+ my $tinfo= shift;
+
+ my $tname= $tinfo->{'name'};
+
+ if ( $glob_use_running_server or $glob_use_embedded_server )
{
- $cmdline_mysqlimport .=
- " --debug=d:t:A,$opt_vardir/log/mysqlimport.trace";
+ return;
}
- my $cmdline_mysqlshow= "$exe_mysqlshow -uroot " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} --password=";
- if ( $opt_debug )
+ # -------------------------------------------------------
+ # Init variables that can change between server starts
+ # -------------------------------------------------------
+ $ENV{'TZ'}= $tinfo->{'timezone'};
+
+ if ( $tinfo->{'component_id'} eq 'mysqld' )
{
- $cmdline_mysqlshow .=
- " --debug=d:t:A,$opt_vardir/log/mysqlshow.trace";
- }
+ if ( ! $opt_skip_ndbcluster and
+ !$clusters->[0]->{'pid'} and
+ $tinfo->{'ndb_test'} )
+ {
+ # Test need cluster, cluster is not started, start it
+ ndbcluster_start($clusters->[0], "");
+ }
- my $cmdline_mysqlbinlog=
- "$exe_mysqlbinlog --no-defaults --local-load=$opt_tmpdir";
+ if ( !$master->[0]->{'pid'} )
+ {
+ # Master mysqld is not started
+ do_before_start_master($tname,$tinfo->{'master_sh'});
- if ( $opt_debug )
+ mysqld_start($master->[0],$tinfo->{'master_opt'},[]);
+
+ }
+
+ if ( $clusters->[0]->{'pid'} and ! $master->[1]->{'pid'} )
+ {
+ # Test needs cluster, start an extra mysqld connected to cluster
+
+ # First wait for first mysql server to have created ndb system tables ok
+ # FIXME This is a workaround so that only one mysqld creates the tables
+ if ( ! sleep_until_file_created(
+ "$master->[0]->{'path_myddir'}/cluster/apply_status.ndb",
+ $master->[0]->{'start_timeout'},
+ $master->[0]->{'pid'}))
+ {
+ mtr_report("Failed to create 'cluster/apply_status' table");
+ report_failure_and_restart($tinfo);
+ return;
+ }
+ mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+
+ mysqld_start($master->[1],$tinfo->{'master_opt'},[]);
+ }
+
+ if ( $tinfo->{'master_restart'} )
+ {
+ # Save this test case information, so next can examine it
+ $master->[0]->{'running_master_is_special'}= $tinfo;
+ }
+ }
+ elsif ( ! $opt_skip_im and $tinfo->{'component_id'} eq 'im' )
{
- $cmdline_mysqlbinlog .=
- " --debug=d:t:A,$opt_vardir/log/mysqlbinlog.trace";
+ # We have to create defaults file every time, in order to ensure that it
+ # will be the same for each test. The problem is that test can change the
+ # file (by SET/UNSET commands), so w/o recreating the file, execution of
+ # one test can affect the other.
+
+ im_create_defaults_file($instance_manager);
+
+ unless ( mtr_im_start($instance_manager, $tinfo->{im_opts}) )
+ {
+ report_failure_and_restart($tinfo);
+ mtr_report("Failed to start Instance Manager. " .
+ "The test '$tname' is marked as failed.");
+ return;
+ }
}
- my $cmdline_mysql=
- "$exe_mysql --host=localhost --user=root --password= " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'}";
+ # ----------------------------------------------------------------------
+ # Start slaves - if needed
+ # ----------------------------------------------------------------------
+ if ( $tinfo->{'slave_num'} )
+ {
+ mtr_tofile($slave->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n");
- my $cmdline_mysql_client_test=
- "$exe_mysql_client_test --no-defaults --testcase --user=root --silent " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'}";
+ restore_slave_databases($tinfo->{'slave_num'});
- if ( $glob_use_embedded_server )
+ do_before_start_slave($tname,$tinfo->{'slave_sh'});
+
+ if ( ! $opt_skip_ndbcluster_slave and
+ !$clusters->[1]->{'pid'} and
+ $tinfo->{'ndb_test'} )
+ {
+ # Test need slave cluster, cluster is not started, start it
+ ndbcluster_start($clusters->[1], "");
+ }
+
+ for ( my $idx= 0; $idx < $tinfo->{'slave_num'}; $idx++ )
+ {
+ if ( ! $slave->[$idx]->{'pid'} )
+ {
+ mysqld_start($slave->[$idx],$tinfo->{'slave_opt'},
+ $tinfo->{'slave_mi'});
+
+ }
+ }
+
+ if ( $tinfo->{'slave_restart'} )
+ {
+ # Save this test case information, so next can examine it
+ $slave->[0]->{'running_slave_is_special'}= $tinfo;
+ }
+
+ }
+
+ # Wait for clusters to start
+ foreach my $cluster (@{$clusters})
{
- $cmdline_mysql_client_test.=
- " -A --language=$path_language" .
- " -A --datadir=$slave->[0]->{'path_myddir'}" .
- " -A --character-sets-dir=$path_charsetsdir";
+
+ next if !$cluster->{'pid'};
+
+ if (ndbcluster_wait_started($cluster, ""))
+ {
+ # failed to start
+ mtr_report("Start of $cluster->{'name'} cluster failed, ");
+ }
}
- my $cmdline_mysql_fix_system_tables=
- "$exe_mysql_fix_system_tables --no-defaults --host=localhost --user=root --password= " .
- "--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'}";
+ # Wait for mysqld's to start
+ foreach my $mysqld (@{$master},@{$slave})
+ {
+ next if !$mysqld->{'pid'};
+ if (mysqld_wait_started($mysqld))
+ {
+ mtr_warning("Failed to start $mysqld->{'type'} mysqld $mysqld->{'idx'}");
+ }
+ }
+}
- # FIXME really needing a PATH???
- # $ENV{'PATH'}= "/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$ENV{'PATH'}";
+#
+# Run include/check-testcase.test
+# Before a testcase, run in record mode, save result file to var
+# After testcase, run and compare with the recorded file, they should be equal!
+#
+sub run_check_testcase ($$) {
- $ENV{'MYSQL'}= $cmdline_mysql;
- $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
- $ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport;
- $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
- $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
- $ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables;
- $ENV{'MYSQL_CLIENT_TEST'}= $cmdline_mysql_client_test;
- $ENV{'CHARSETSDIR'}= $path_charsetsdir;
- $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults;
+ my $mode= shift;
+ my $mysqld= shift;
- $ENV{'NDB_STATUS_OK'}= $flag_ndb_status_ok;
- $ENV{'NDB_MGM'}= $exe_ndb_mgm;
- $ENV{'NDB_BACKUP_DIR'}= $path_ndb_backup_dir;
- $ENV{'NDB_TOOLS_DIR'}= $path_ndb_tools_dir;
- $ENV{'NDB_TOOLS_OUTPUT'}= $file_ndb_testrun_log;
- $ENV{'NDB_CONNECTSTRING'}= $opt_ndbconnectstring;
+ my $name= "check-" . $mysqld->{'type'} . $mysqld->{'idx'};
- my $exe= $exe_mysqltest;
my $args;
-
mtr_init_args(\$args);
mtr_add_arg($args, "--no-defaults");
- mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
+ mtr_add_arg($args, "--silent");
+ mtr_add_arg($args, "-v");
+ mtr_add_arg($args, "--skip-safemalloc");
+ mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
+
+ mtr_add_arg($args, "--socket=%s", $mysqld->{'path_sock'});
+ mtr_add_arg($args, "--port=%d", $mysqld->{'port'});
mtr_add_arg($args, "--database=test");
mtr_add_arg($args, "--user=%s", $opt_user);
mtr_add_arg($args, "--password=");
+
+ mtr_add_arg($args, "-R");
+ mtr_add_arg($args, "$opt_vardir/tmp/$name.result");
+
+ if ( $mode eq "before" )
+ {
+ mtr_add_arg($args, "--record");
+ }
+
+ my $res = mtr_run_test($exe_mysqltest,$args,
+ "include/check-testcase.test", "", "", "");
+
+ if ( $res == 1 and $mode = "after")
+ {
+ mtr_run("diff",["-u",
+ "$opt_vardir/tmp/$name.result",
+ "$opt_vardir/tmp/$name.reject"],
+ "", "", "", "");
+ }
+ elsif ( $res )
+ {
+ mtr_error("Could not execute 'check-testcase' $mode testcase");
+ }
+}
+
+
+
+sub run_mysqltest ($) {
+ my ($tinfo)= @_;
+ my $exe= $exe_mysqltest;
+ my $args;
+
+ mtr_init_args(\$args);
+
+ mtr_add_arg($args, "--no-defaults");
mtr_add_arg($args, "--silent");
mtr_add_arg($args, "-v");
mtr_add_arg($args, "--skip-safemalloc");
mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
- mtr_add_arg($args, "--port=%d", $master->[0]->{'path_myport'});
+
+ if ($tinfo->{'component_id'} eq 'im')
+ {
+ mtr_add_arg($args, "--socket=%s", $instance_manager->{'path_sock'});
+ mtr_add_arg($args, "--port=%d", $instance_manager->{'port'});
+ mtr_add_arg($args, "--user=%s", $instance_manager->{'admin_login'});
+ mtr_add_arg($args, "--password=%s", $instance_manager->{'admin_password'});
+ }
+ else # component_id == mysqld
+ {
+ mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'});
+ mtr_add_arg($args, "--port=%d", $master->[0]->{'port'});
+ mtr_add_arg($args, "--database=test");
+ mtr_add_arg($args, "--user=%s", $opt_user);
+ mtr_add_arg($args, "--password=");
+ }
if ( $opt_ps_protocol )
{
mtr_add_arg($args, "--ps-protocol");
}
+ 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");
+ }
+
if ( $opt_strace_client )
{
$exe= "strace"; # FIXME there are ktrace, ....
@@ -2392,6 +3869,11 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "--big-test");
}
+ if ( $opt_valgrind )
+ {
+ mtr_add_arg($args, "--valgrind");
+ }
+
if ( $opt_compress )
{
mtr_add_arg($args, "--compress");
@@ -2404,17 +3886,30 @@ sub run_mysqltest ($) {
if ( $opt_debug )
{
- mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace", $opt_vardir);
+ mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace",
+ $path_vardir_trace);
}
- if ( $opt_with_openssl )
+ if ( $opt_ssl_supported )
{
mtr_add_arg($args, "--ssl-ca=%s/std_data/cacert.pem",
- $glob_mysql_test_dir);
+ $glob_mysql_test_dir);
mtr_add_arg($args, "--ssl-cert=%s/std_data/client-cert.pem",
- $glob_mysql_test_dir);
+ $glob_mysql_test_dir);
mtr_add_arg($args, "--ssl-key=%s/std_data/client-key.pem",
- $glob_mysql_test_dir);
+ $glob_mysql_test_dir);
+ }
+
+ if ( $opt_ssl )
+ {
+ # Turn on SSL for _all_ test cases if option --ssl was used
+ mtr_add_arg($args, "--ssl",
+ $glob_mysql_test_dir);
+ }
+ elsif ( $opt_ssl_supported )
+ {
+ mtr_add_arg($args, "--skip-ssl",
+ $glob_mysql_test_dir);
}
# ----------------------------------------------------------------------
@@ -2435,7 +3930,7 @@ sub run_mysqltest ($) {
# Add arguments that should not go into the MYSQL_TEST env var
# ----------------------------------------------------------------------
- if ( defined $opt_valgrind_mysqltest )
+ if ( $opt_valgrind_mysqltest )
{
# Prefix the Valgrind options to the argument list.
# We do this here, since we do not want to Valgrind the nested invocations
@@ -2446,7 +3941,10 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "%s", $_) for @args_saved;
}
- mtr_add_arg($args, "-R");
+ mtr_add_arg($args, "--test-file");
+ mtr_add_arg($args, $tinfo->{'path'});
+
+ mtr_add_arg($args, "--result-file");
mtr_add_arg($args, $tinfo->{'result_file'});
if ( $opt_record )
@@ -2454,36 +3952,248 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "--record");
}
- return mtr_run_test($exe,$args,$tinfo->{'path'},"",$path_timefile,"");
+ if ( $opt_client_gdb )
+ {
+ gdb_arguments(\$args, \$exe, "client");
+ }
+ elsif ( $opt_client_ddd )
+ {
+ ddd_arguments(\$args, \$exe, "client");
+ }
+ elsif ( $opt_client_debugger )
+ {
+ debugger_arguments(\$args, \$exe, "client");
+ }
+
+ if ($exe_libtool and $opt_valgrind)
+ {
+ # 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;
+ }
+
+ if ( $opt_check_testcases )
+ {
+ foreach my $mysqld (@{$master}, @{$slave})
+ {
+ if ($mysqld->{'pid'})
+ {
+ run_check_testcase("before", $mysqld);
+ }
+ }
+ }
+
+ my $res = mtr_run_test($exe,$args,"","",$path_timefile,"");
+
+ if ( $opt_check_testcases )
+ {
+ foreach my $mysqld (@{$master}, @{$slave})
+ {
+ if ($mysqld->{'pid'})
+ {
+ run_check_testcase("after", $mysqld);
+ }
+ }
+ }
+
+ return $res;
+
}
-sub valgrind_arguments {
+#
+# 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);
+ my $gdb_init_file= "$opt_tmpdir/gdbinit.$type";
+
+ # Remove the old gdbinit file
+ unlink($gdb_init_file);
+
+ if ( $type eq "client" )
+ {
+ # write init file for client
+ mtr_tofile($gdb_init_file,
+ "set args $str\n" .
+ "break main\n");
+ }
+ 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" .
+ "run");
+ }
+
+ if ( $opt_manual_gdb )
+ {
+ print "\nTo start gdb for $type, type in another window:\n";
+ print "cd $glob_mysql_test_dir;\n";
+ print "gdb -x $gdb_init_file $$exe\n";
+
+ # Indicate the exe should not be started
+ $$exe= undef;
+ return;
+ }
+
+ $$args= [];
+ mtr_add_arg($$args, "-title");
+ mtr_add_arg($$args, "$type");
+ mtr_add_arg($$args, "-e");
+
+ if ( $exe_libtool )
+ {
+ mtr_add_arg($$args, $exe_libtool);
+ 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";
+}
+
+
+#
+# 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);
+ my $gdb_init_file= "$opt_tmpdir/gdbinit.$type";
- 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";
+ # Remove the old gdbinit file
+ unlink($gdb_init_file);
- if ( defined $opt_valgrind_all )
+ if ( $type eq "client" )
{
- mtr_add_arg($args, "-v");
- mtr_add_arg($args, "--show-reachable=yes");
+ # write init file for client
+ mtr_tofile($gdb_init_file,
+ "set args $str\n" .
+ "break main\n");
}
+ 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" .
+ "end");
+ }
+
+ if ( $opt_manual_ddd )
+ {
+ print "\nTo start ddd for $type, type in another window:\n";
+ print "cd $glob_mysql_test_dir;\n";
+ print "ddd -x $gdb_init_file $$exe\n";
- if ( $opt_valgrind_options )
+ # Indicate the exe should not be started
+ $$exe= undef;
+ return;
+ }
+
+ my $save_exe= $$exe;
+ $$args= [];
+ if ( $exe_libtool )
+ {
+ $$exe= $exe_libtool;
+ mtr_add_arg($$args, "--mode=execute");
+ mtr_add_arg($$args, "ddd");
+ }
+ else
{
- # FIXME split earlier and put into @glob_valgrind_*
- mtr_add_arg($args, '%s', $_) for (split(' ', $opt_valgrind_options));
+ $$exe= "ddd";
}
+ mtr_add_arg($$args, "--command=$gdb_init_file");
+ mtr_add_arg($$args, "$save_exe");
+}
+
+
+#
+# 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;
+
+ # FIXME Need to change the below "eq"'s to
+ # "case unsensitive string contains"
+ if ( $debugger eq "vcexpress" or $debugger eq "vc")
+ {
+ # vc[express] /debugexe exe arg1 .. argn
+
+ # Add /debugexe and name of the exe before args
+ unshift(@$$args, "/debugexe");
+ unshift(@$$args, "$$exe");
+
+ }
+ elsif ( $debugger eq "windbg" )
+ {
+ # windbg exe arg1 .. argn
+
+ # Add name of the exe before args
+ unshift(@$$args, "$$exe");
+
+ }
+ else
+ {
+ mtr_error("Unknown argument \"$debugger\" passed to --debugger");
+ }
+
+ # Set exe to debuggername
+ $$exe= $debugger;
+}
+
+
+#
+# Modify the exe and args so that program is run in valgrind
+#
+sub valgrind_arguments {
+ my $args= shift;
+ my $exe= shift;
+
+ 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";
+ }
+
+ # Add valgrind options, can be overriden by user
+ mtr_add_arg($args, '%s', $_) for (split(' ', $opt_valgrind_options));
mtr_add_arg($args, $$exe);
- $$exe= $opt_valgrind || "valgrind";
+ $$exe= $opt_valgrind_path || "valgrind";
}
@@ -2503,38 +4213,60 @@ sub usage ($) {
print STDERR <<HERE;
-mysql-test-run [ OPTIONS ] [ TESTCASE ]
-
-FIXME when is TESTCASE arg used or not?!
+$0 [ OPTIONS ] [ TESTCASE ]
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
- bench Run the benchmark suite FIXME
- small-bench FIXME
- no-manager Use the istanse manager (currently disabled)
+ 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
+ compress Use the compressed protocol between client and server
+ ssl Use ssl protocol between client and server
+ skip-ssl Dont start server with support for ssl connections
+ bench Run the benchmark suite
+ small-bench Run the benchmarks with --small-tests --small-tables
+
+Options to control directories to use
+ benchdir=DIR The directory where the benchmark suite is stored
+ (default: ../../mysql-bench)
+ tmpdir=DIR The directory where temporary files are stored
+ (default: ./var/tmp).
+ vardir=DIR The directory where files generated from the test run
+ is stored (default: ./var). Specifying a ramdisk or
+ tmpfs will speed up tests.
Options to control what test suites or cases to run
force Continue to run the suite after failure
- with-ndbcluster Use cluster, and enable test cases that requres it
+ with-ndbcluster Use cluster in all tests
+ with-ndbcluster-only Run only tests that include "ndb" in the filename
+ skip-ndb[cluster] Skip all tests that need cluster
+ skip-ndb[cluster]-slave Skip all tests that need a slave cluster
+ ndb-extra Run extra tests from ndb directory
do-test=PREFIX Run test cases which name are prefixed with PREFIX
start-from=PREFIX Run test cases starting from test prefixed with PREFIX
suite=NAME Run the test suite named NAME. The default is "main"
skip-rpl Skip the replication test cases.
+ skip-im Don't start IM, and skip the IM test cases
skip-test=PREFIX Skip test cases which name are prefixed with PREFIX
+ big-test Pass "--big-test" to mysqltest which will set the
+ environment variable BIG_TEST, which can be checked
+ from test cases.
Options that specify ports
master_port=PORT Specify the port number used by the first master
slave_port=PORT Specify the port number used by the first slave
- ndbcluster_port=PORT Specify the port number used by cluster
- manager-port=PORT Specify the port number used by manager (currently not used)
+ ndbcluster-port=PORT Specify the port number used by cluster
+ ndbcluster-port-slave=PORT Specify the port number used by slave cluster
Options for test case authoring
record TESTNAME (Re)genereate the result file for TESTNAME
+ check-testcases Check testcases for sideeffects
Options that pass on options
@@ -2543,65 +4275,72 @@ Options that pass on options
Options to run test on running server
extern Use running server for tests FIXME DANGEROUS
- ndbconnectstring=STR Use running cluster, and connect using STR
+ ndb-connectstring=STR Use running cluster, and connect using STR
+ ndb-connectstring-slave=STR Use running slave cluster, and connect using STR
user=USER User for connect to server
Options for debugging the product
- gdb FIXME
- manual-gdb FIXME
- client-gdb FIXME
- ddd FIXME
- strace-client FIXME
+ client-ddd Start mysqltest client in ddd
+ client-debugger=NAME Start mysqltest in the selected debugger
+ client-gdb Start mysqltest client in gdb
+ ddd Start mysqld in ddd
+ debug Dump trace output for all servers and client programs
+ debugger=NAME Start mysqld in the selected debugger
+ 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)
master-binary=PATH Specify the master "mysqld" to use
slave-binary=PATH Specify the slave "mysqld" to use
+ strace-client Create strace output for mysqltest client
Options for coverage, profiling etc
gcov FIXME
gprof FIXME
- valgrind[=EXE] Run the "mysqltest" executable as well as the "mysqld"
- server using valgrind, optionally specifying the
- executable path/name
- valgrind-mysqltest[=EXE] In addition, run the "mysqltest" executable with valgrind
- valgrind-all[=EXE] Adds verbose flag, and --show-reachable to valgrind
- valgrind-options=ARGS Extra options to give valgrind
+ valgrind Run the "mysqltest" and "mysqld" executables using
+ valgrind with options($default_valgrind_options)
+ valgrind-all Synonym for --valgrind
+ valgrind-mysqltest Run the "mysqltest" executable with valgrind
+ valgrind-mysqld Run the "mysqld" executable with valgrind
+ valgrind-options=ARGS Options to give valgrind, replaces default options
+ valgrind-path=[EXE] Path to the valgrind executable
+ callgrind Instruct valgrind to use callgrind
Misc options
- verbose Verbose output from this script
- script-debug Debug this script itself
comment=STR Write STR to the output
- compress Use the compressed protocol between client and server
- timer Show test case execution time
- start-and-exit Only initiate and start the "mysqld" servers, use the startup
- settings for the specified test case if any
- start-dirty Only start the "mysqld" servers without initiation
- fast Don't try to cleanup from earlier runs
- reorder Reorder tests to get less server restarts
+ notimer Don't show test case execution time
+ script-debug Debug this script itself
+ verbose More verbose output
+ start-and-exit Only initialize and start the servers, using the
+ startup settings for the specified test case (if any)
+ start-dirty Only start the servers (without initialization) for
+ the specified test case (if any)
+ fast Don't try to clean up from earlier runs
+ reorder Reorder tests to get fewer server restarts
help Get this help text
unified-diff | udiff When presenting differences, use unified diff
- testcase-timeout=MINUTES Max test case run time (default 5)
- suite-timeout=MINUTES Max test suite run time (default 120)
+ testcase-timeout=MINUTES Max test case run time (default $default_testcase_timeout)
+ suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout)
-Options not yet described, or that I want to look into more
+Deprecated options
+ with-openssl Deprecated option for ssl
- big-test
- debug
+
+Options not yet described, or that I want to look into more
local
- local-master
netware
- old-master
sleep=SECONDS
socket=PATH
- tmpdir=DIR
user-test=s
wait-timeout=SECONDS
warnings
log-warnings
- with-openssl
HERE
mtr_exit(1);
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 7276397bdc7..4c243a64484 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -163,7 +163,7 @@ mysqltest: At line 1: Invalid argument to error: '1sssss' - the errno may only c
mysqltest: At line 1: The sqlstate must be exactly 5 chars long
mysqltest: At line 1: The sqlstate may only consist of digits[0-9] and _uppercase_ letters
mysqltest: At line 1: The sqlstate must be exactly 5 chars long
-mysqltest: At line 1: Not available in mysqltest for MySQL 4.1.22
+mysqltest: At line 1: Not available in this version of mysqltest
mysqltest: At line 1: Invalid argument to error: '999e9' - the errno may only consist of digits[0-9]
mysqltest: At line 1: Invalid argument to error: '9b' - the errno may only consist of digits[0-9]
mysqltest: At line 1: Too many errorcodes specified