summaryrefslogtreecommitdiff
path: root/mysql-test/mysql-test-run.pl
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/mysql-test-run.pl')
-rwxr-xr-xmysql-test/mysql-test-run.pl1490
1 files changed, 909 insertions, 581 deletions
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 51808f8df34..bfe2c07896b 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -84,7 +84,7 @@ use File::Basename;
use File::Copy;
use File::Find;
use File::Temp qw/tempdir/;
-use File::Spec::Functions qw/splitdir/;
+use File::Spec::Functions qw/splitdir rel2abs/;
use My::Platform;
use My::SafeProcess;
use My::ConfigFactory;
@@ -122,6 +122,7 @@ our $path_testlog;
our $default_vardir;
our $opt_vardir; # Path to use for var/ dir
+our $plugindir;
my $path_vardir_trace; # unix formatted opt_vardir for trace files
my $opt_tmpdir; # Path to use for tmp/ dir
my $opt_tmpdir_pid;
@@ -159,7 +160,7 @@ our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
# If you add a new suite, please check TEST_DIRS in Makefile.am.
#
-my $DEFAULT_SUITES= "main,sys_vars,binlog,federated,rpl,rpl_ndb,ndb,innodb,perfschema";
+my $DEFAULT_SUITES= "main,sys_vars,binlog,federated,rpl,maria,parts,innodb,innodb_plugin,percona,ndb,vcol,oqgraph,sphinx,perfschema";
my $opt_suites;
our $opt_verbose= 0; # Verbose output, enable with --verbose
@@ -169,10 +170,12 @@ our $exe_mysqltest;
our $exe_libtool;
our $opt_big_test= 0;
+our $opt_staging_run= 0;
our @opt_combinations;
our @opt_extra_mysqld_opt;
+our @opt_extra_mysqltest_opt;
my $opt_compress;
my $opt_ssl;
@@ -197,6 +200,7 @@ our $opt_force;
our $opt_mem= $ENV{'MTR_MEM'};
our $opt_gcov;
+our $opt_gcov_src_dir;
our $opt_gcov_exe= "gcov";
our $opt_gcov_err= "mysql-test-gcov.msg";
our $opt_gcov_msg= "mysql-test-gcov.err";
@@ -239,7 +243,7 @@ my $opt_max_connections;
my $opt_sleep;
my $opt_testcase_timeout= $ENV{MTR_TESTCASE_TIMEOUT} || 15; # minutes
-my $opt_suite_timeout = $ENV{MTR_SUITE_TIMEOUT} || 300; # minutes
+my $opt_suite_timeout = $ENV{MTR_SUITE_TIMEOUT} || 360; # minutes
my $opt_shutdown_timeout= $ENV{MTR_SHUTDOWN_TIMEOUT} || 10; # seconds
my $opt_start_timeout = $ENV{MTR_START_TIMEOUT} || 180; # seconds
@@ -249,7 +253,7 @@ sub check_timeout { return $opt_testcase_timeout * 6; };
my $opt_wait_all;
my $opt_user_args;
my $opt_repeat= 1;
-my $opt_retry= 3;
+my $opt_retry= 1;
my $opt_retry_failure= env_or_val(MTR_RETRY_FAILURE => 2);
my $opt_reorder= 1;
my $opt_force_restart= 0;
@@ -259,10 +263,12 @@ my $opt_strace_client;
our $opt_user = "root";
my $opt_valgrind= 0;
-my $opt_valgrind_mysqld= 0;
-my $opt_valgrind_mysqltest= 0;
my @default_valgrind_args= ("--show-reachable=yes");
my @valgrind_args;
+our $opt_valgrind_mysqld= 0;
+my $opt_valgrind_mysqltest= 0;
+my $opt_strace= 0;
+my @strace_args;
my $opt_valgrind_path;
my $opt_callgrind;
my %mysqld_logs;
@@ -292,6 +298,8 @@ our $debug_compiled_binaries;
our %mysqld_variables;
+our %suites;
+
my $source_dist= 0;
my $opt_max_save_core= env_or_val(MTR_MAX_SAVE_CORE => 5);
@@ -300,6 +308,11 @@ my $opt_max_test_fail= env_or_val(MTR_MAX_TEST_FAIL => 10);
my $opt_parallel= $ENV{MTR_PARALLEL} || 1;
+# lock file to stop tests
+my $opt_stop_file= $ENV{MTR_STOP_FILE};
+# print messages when test suite is stopped (for buildbot)
+my $opt_stop_keep_alive= $ENV{MTR_STOP_KEEP_ALIVE};
+
select(STDOUT);
$| = 1; # Automatically flush STDOUT
@@ -321,7 +334,7 @@ sub main {
My::SafeProcess::find_bin();
if ( $opt_gcov ) {
- gcov_prepare($basedir);
+ gcov_prepare($basedir . "/" . $opt_gcov_src_dir);
}
if (!$opt_suites) {
@@ -348,6 +361,26 @@ sub main {
}
}
+ print "vardir: $opt_vardir\n";
+ initialize_servers();
+
+ mtr_report("Checking supported features...");
+ if (using_extern())
+ {
+ # Connect to the running mysqld and find out what it supports
+ collect_mysqld_features_from_running_server();
+ }
+ else
+ {
+ # Run the mysqld to find out what features are available
+ collect_mysqld_features();
+ }
+ check_ndbcluster_support(\%mysqld_variables);
+ check_ssl_support(\%mysqld_variables);
+ check_debug_support(\%mysqld_variables);
+
+ executable_setup();
+
mtr_report("Collecting tests...");
my $tests= collect_test_cases($opt_reorder, $opt_suites, \@opt_cases, \@opt_skip_test_list);
@@ -365,9 +398,6 @@ sub main {
unshift(@$tests, $tinfo);
}
- print "vardir: $opt_vardir\n";
- initialize_servers();
-
#######################################################################
my $num_tests= @$tests;
if ( $opt_parallel eq "auto" ) {
@@ -430,7 +460,8 @@ sub main {
mtr_print_thick_line();
mtr_print_header();
- my $completed= run_test_server($server, $tests, $opt_parallel);
+ my ($prefix, $fail, $completed, $extra_warnings)=
+ run_test_server($server, $tests, $opt_parallel);
exit(0) if $opt_start_exit;
@@ -465,18 +496,21 @@ sub main {
# Not all tests completed, failure
mtr_report();
mtr_report("Only ", int(@$completed), " of $num_tests completed.");
- mtr_error("Not all tests completed");
}
mtr_print_line();
if ( $opt_gcov ) {
- gcov_collect($basedir, $opt_gcov_exe,
+ gcov_collect($basedir . "/" . $opt_gcov_src_dir, $opt_gcov_exe,
$opt_gcov_msg, $opt_gcov_err);
}
- mtr_report_stats("Completed", $completed);
+ mtr_report_stats($prefix, $fail, $completed, $extra_warnings);
+ if ( @$completed != $num_tests)
+ {
+ mtr_error("Not all tests completed");
+ }
exit(0);
}
@@ -487,6 +521,8 @@ sub run_test_server ($$$) {
my $num_saved_cores= 0; # Number of core files saved in vardir/log/ so far.
my $num_saved_datadir= 0; # Number of datadirs saved in vardir/log/ so far.
my $num_failed_test= 0; # Number of tests failed so far
+ my $test_failure= 0; # Set true if test suite failed
+ my $extra_warnings= []; # Warnings found during server shutdowns
# Scheduler variables
my $max_ndb= $childs / 2;
@@ -504,6 +540,14 @@ sub run_test_server ($$$) {
my $s= IO::Select->new();
$s->add($server);
while (1) {
+ if ($opt_stop_file)
+ {
+ if (mtr_wait_lock_file($opt_stop_file, $opt_stop_keep_alive))
+ {
+ # We were waiting so restart timer process
+ my $suite_timeout= start_timer(suite_timeout());
+ }
+ }
my @ready = $s->can_read(1); # Wake up once every second
foreach my $sock (@ready) {
if ($sock == $server) {
@@ -520,7 +564,7 @@ sub run_test_server ($$$) {
mtr_verbose("Child closed socket");
$s->remove($sock);
if (--$childs == 0){
- return $completed;
+ return ("Completed", $test_failure, $completed, $extra_warnings);
}
next;
}
@@ -586,18 +630,18 @@ sub run_test_server ($$$) {
$num_failed_test++ unless ($result->{retries} ||
$result->{exp_fail});
+ $test_failure= 1;
if ( !$opt_force ) {
# Test has failed, force is off
push(@$completed, $result);
- return $completed;
+ return ("Failure", 1, $completed, $extra_warnings);
}
elsif ($opt_max_test_fail > 0 and
$num_failed_test >= $opt_max_test_fail) {
push(@$completed, $result);
- mtr_report_stats("Too many failed", $completed, 1);
mtr_report("Too many tests($num_failed_test) failed!",
"Terminating...");
- return undef;
+ return ("Too many failed", 1, $completed, $extra_warnings);
}
}
@@ -649,7 +693,19 @@ sub run_test_server ($$$) {
elsif ($line eq 'START'){
; # Send first test
}
- else {
+ elsif ($line eq 'WARNINGS'){
+ my $fake_test= My::Test::read_test($sock);
+ my $test_list= join (" ", @{$fake_test->{testnames}});
+ push @$extra_warnings, $test_list;
+ my $report= $fake_test->{'warnings'};
+ mtr_report("***Warnings generated in error logs during shutdown ".
+ "after running tests: $test_list\n\n$report");
+ $test_failure= 1;
+ if ( !$opt_force ) {
+ # Test failure due to warnings, force is off
+ return ("Warnings in log", 1, $completed, $extra_warnings);
+ }
+ } else {
mtr_error("Unknown response: '$line' from client");
}
@@ -707,6 +763,8 @@ sub run_test_server ($$$) {
$next= splice(@$tests, $second_best, 1);
}
+ xterm_stat(scalar(@$tests));
+
if ($next) {
#$next->print_test();
$next->write_test($sock, 'TESTCASE');
@@ -726,9 +784,8 @@ sub run_test_server ($$$) {
# ----------------------------------------------------
if ( has_expired($suite_timeout) )
{
- mtr_report_stats("Timeout", $completed, 1);
mtr_report("Test suite timeout! Terminating...");
- return undef;
+ return ("Timeout", 1, $completed, $extra_warnings);
}
}
}
@@ -793,7 +850,7 @@ sub run_worker ($) {
$test->{worker} = $thread_num if $opt_parallel > 1;
- run_testcase($test);
+ run_testcase($test, $server);
#$test->{result}= 'MTR_RES_PASSED';
# Send it back, now with results set
#$test->print_test();
@@ -801,9 +858,17 @@ sub run_worker ($) {
}
elsif ($line eq 'BYE'){
mtr_report("Server said BYE");
- stop_all_servers($opt_shutdown_timeout);
- if ($opt_valgrind_mysqld) {
- valgrind_exit_reports();
+ # We need to gracefully shut down the servers to see any
+ # Valgrind memory leak errors etc. since last server restart.
+ if ($opt_warnings) {
+ stop_servers(reverse all_servers());
+ if(check_warnings_post_shutdown($server)) {
+ # Warnings appeared in log file(s) during final server shutdown.
+ exit(1);
+ }
+ }
+ else {
+ stop_all_servers($opt_shutdown_timeout);
}
if ( $opt_gprof ) {
gprof_collect (find_mysqld($basedir), keys %gprof_dirs);
@@ -865,7 +930,7 @@ sub command_line_setup {
'ssl|with-openssl' => \$opt_ssl,
'skip-ssl' => \$opt_skip_ssl,
'compress' => \$opt_compress,
- 'vs-config' => \$opt_vs_config,
+ 'vs-config=s' => \$opt_vs_config,
# Max number of parallel threads to use
'parallel=s' => \$opt_parallel,
@@ -890,6 +955,7 @@ sub command_line_setup {
'skip-combinations' => \&collect_option,
'experimental=s' => \@opt_experimentals,
'skip-im' => \&ignore_option,
+ 'staging-run' => \$opt_staging_run,
# Specify ports
'build-thread|mtr-build-thread=i' => \$opt_build_thread,
@@ -903,6 +969,9 @@ sub command_line_setup {
# Extra options used when starting mysqld
'mysqld=s' => \@opt_extra_mysqld_opt,
+ # Extra options used when starting mysqltest
+ 'mysqltest=s' => \@opt_extra_mysqltest_opt,
+
# Run test on running server
'extern=s' => \%opts_extern, # Append to hash
@@ -917,13 +986,16 @@ sub command_line_setup {
'manual-ddd' => \$opt_manual_ddd,
'debugger=s' => \$opt_debugger,
'client-debugger=s' => \$opt_client_debugger,
+ 'strace' => \$opt_strace,
'strace-client:s' => \$opt_strace_client,
+ 'strace-option=s' => \@strace_args,
'max-save-core=i' => \$opt_max_save_core,
'max-save-datadir=i' => \$opt_max_save_datadir,
'max-test-fail=i' => \$opt_max_test_fail,
# Coverage, profiling etc
'gcov' => \$opt_gcov,
+ 'gcov-src-dir=s' => \$opt_gcov_src_dir,
'gprof' => \$opt_gprof,
'valgrind|valgrind-all' => \$opt_valgrind,
'valgrind-mysqltest' => \$opt_valgrind_mysqltest,
@@ -978,6 +1050,8 @@ sub command_line_setup {
'warnings!' => \$opt_warnings,
'timestamp' => \&report_option,
'timediff' => \&report_option,
+ 'stop-file=s' => \$opt_stop_file,
+ 'stop-keep-alive=i' => \$opt_stop_keep_alive,
'max-connections=i' => \$opt_max_connections,
'default-myisam!' => \&collect_option,
@@ -987,7 +1061,6 @@ sub command_line_setup {
);
GetOptions(%options) or usage("Can't read options");
-
usage("") if $opt_usage;
list_options(\%options) if $opt_list_options;
@@ -1030,7 +1103,15 @@ sub command_line_setup {
{
$basedir= dirname($basedir);
}
-
+ # For .deb, it's like RPM, but installed in /usr/share/mysql/mysql-test.
+ # So move up one more directory level yet.
+ if ( ! $source_dist and ! -d "$basedir/bin" )
+ {
+ $basedir= dirname($basedir);
+ }
+
+ fix_vs_config_dir();
+
# Respect MTR_BINDIR variable, which is typically set in to the
# build directory in out-of-source builds.
$bindir=$ENV{MTR_BINDIR}||$basedir;
@@ -1045,31 +1126,22 @@ sub command_line_setup {
{
$path_client_bindir= mtr_path_exists("$bindir/client_release",
"$bindir/client_debug",
- vs_config_dirs('client', ''),
+ "$bindir/client$opt_vs_config",
"$bindir/client",
"$bindir/bin");
}
# Look for language files and charsetsdir, use same share
- $path_language= mtr_path_exists("$bindir/share/mysql",
+ $path_language= mtr_path_exists("$bindir/share/mariadb",
+ "$bindir/share/mysql",
"$bindir/sql/share",
"$bindir/share");
my $path_share= $path_language;
- $path_charsetsdir = mtr_path_exists("$basedir/share/mysql/charsets",
+ $path_charsetsdir = mtr_path_exists("$basedir/share/mariadb/charsets",
+ "$basedir/share/mysql/charsets",
"$basedir/sql/share/charsets",
"$basedir/share/charsets");
- if (using_extern())
- {
- # Connect to the running mysqld and find out what it supports
- collect_mysqld_features_from_running_server();
- }
- else
- {
- # Run the mysqld to find out what features are available
- collect_mysqld_features();
- }
-
if ( $opt_comment )
{
mtr_report();
@@ -1143,6 +1215,12 @@ sub command_line_setup {
}
}
+ if ( @opt_cases )
+ {
+ # Run big tests if explicitely specified on command line
+ $opt_big_test= 1;
+ }
+
# --------------------------------------------------------------------------
# Find out type of logging that are being used
# --------------------------------------------------------------------------
@@ -1297,7 +1375,7 @@ sub command_line_setup {
# Add the location for libmysqld.dll to the path.
my $separator= ";";
my $lib_mysqld=
- mtr_path_exists(vs_config_dirs('libmysqld',''));
+ mtr_path_exists("$basedir/libmysqld$opt_vs_config");
if ( IS_CYGWIN )
{
$lib_mysqld= posix_path($lib_mysqld);
@@ -1319,21 +1397,18 @@ sub command_line_setup {
if ($opt_gdb)
{
- mtr_warning("Silently converting --gdb to --client-gdb in embedded mode");
$opt_client_gdb= $opt_gdb;
$opt_gdb= undef;
}
if ($opt_ddd)
{
- mtr_warning("Silently converting --ddd to --client-ddd in embedded mode");
$opt_client_ddd= $opt_ddd;
$opt_ddd= undef;
}
if ($opt_debugger)
{
- mtr_warning("Silently converting --debugger to --client-debugger in embedded mode");
$opt_client_debugger= $opt_debugger;
$opt_debugger= undef;
}
@@ -1347,12 +1422,13 @@ sub command_line_setup {
}
# --------------------------------------------------------------------------
- # Big test flags
+ # Big test and staging_run flags
# --------------------------------------------------------------------------
if ( $opt_big_test )
{
$ENV{'BIG_TEST'}= 1;
}
+ $ENV{'STAGING_RUN'}= $opt_staging_run;
# --------------------------------------------------------------------------
# Gcov flag
@@ -1371,6 +1447,11 @@ sub command_line_setup {
{
# Indicate that we are using debugger
$glob_debugger= 1;
+ $opt_testcase_timeout= 60*60*24; # Don't abort debugging with timeout
+ $opt_suite_timeout= $opt_testcase_timeout;
+ $opt_retry= 1;
+ $opt_retry_failure= 1;
+
if ( using_extern() )
{
mtr_error("Can't use --extern when using debugger");
@@ -1391,6 +1472,13 @@ sub command_line_setup {
collect_option ('quick-collect', 1);
$start_only= 1;
}
+ if ($opt_debug)
+ {
+ $opt_testcase_timeout= 60*60*24; # Don't abort debugging with timeout
+ $opt_suite_timeout= $opt_testcase_timeout;
+ $opt_retry= 1;
+ $opt_retry_failure= 1;
+ }
# --------------------------------------------------------------------------
# Check use of user-args
@@ -1467,20 +1555,29 @@ sub command_line_setup {
push(@valgrind_args, @default_valgrind_args)
unless @valgrind_args;
- # Don't add --quiet; you will loose the summary reports.
+ # Make valgrind run in quiet mode so it only print errors
+ push(@valgrind_args, "--quiet" );
mtr_report("Running valgrind with options \"",
join(" ", @valgrind_args), "\"");
}
- mtr_report("Checking supported features...");
-
- check_ndbcluster_support(\%mysqld_variables);
- check_ssl_support(\%mysqld_variables);
- check_debug_support(\%mysqld_variables);
-
- executable_setup();
+ if (@strace_args)
+ {
+ $opt_strace=1;
+ }
+ # InnoDB does not bother to do individual de-allocations at exit. Instead it
+ # relies on a custom allocator to track every allocation, and frees all at
+ # once during exit.
+ # In XtraDB, an option use-sys-malloc is introduced (and on by default) to
+ # disable this (for performance). But this exposes Valgrind to all the
+ # missing de-allocations, so we need to disable it to at least get
+ # meaningful leak checking for the rest of the server.
+ if ($opt_valgrind_mysqld)
+ {
+ push(@opt_extra_mysqld_opt, "--loose-skip-innodb-use-sys-malloc");
+ }
}
@@ -1546,13 +1643,6 @@ sub set_build_thread_ports($) {
sub collect_mysqld_features {
my $found_variable_list_start= 0;
- my $use_tmpdir;
- if ( defined $opt_tmpdir and -d $opt_tmpdir){
- # Create the tempdir in $opt_tmpdir
- $use_tmpdir= $opt_tmpdir;
- }
- my $tmpdir= tempdir(CLEANUP => 0, # Directory removed by this function
- DIR => $use_tmpdir);
#
# Execute "mysqld --no-defaults --help --verbose" to get a
@@ -1566,9 +1656,17 @@ sub collect_mysqld_features {
my $args;
mtr_init_args(\$args);
mtr_add_arg($args, "--no-defaults");
- mtr_add_arg($args, "--datadir=%s", mixed_path($tmpdir));
+ mtr_add_arg($args, "--datadir=%s/tmp", $opt_vardir);
+ mtr_add_arg($args, "--basedir=%s", $basedir);
mtr_add_arg($args, "--lc-messages-dir=%s", $path_language);
mtr_add_arg($args, "--skip-grant-tables");
+ for (@opt_extra_mysqld_opt) {
+ mtr_add_arg($args, $_) unless /^--binlog-format\b/;
+ }
+ my $euid= $>;
+ if (!IS_WINDOWS and $euid == 0) {
+ mtr_add_arg($args, "--user=root");
+ }
mtr_add_arg($args, "--verbose");
mtr_add_arg($args, "--help");
@@ -1582,6 +1680,8 @@ sub collect_mysqld_features {
my $cmd= join(" ", $exe_mysqld, @$args);
my $list= `$cmd`;
+ mtr_verbose("cmd: $cmd");
+
foreach my $line (split('\n', $list))
{
# First look for version
@@ -1595,7 +1695,7 @@ sub collect_mysqld_features {
#print "Major: $1 Minor: $2 Build: $3\n";
$mysql_version_id= $1*10000 + $2*100 + $3;
#print "mysql_version_id: $mysql_version_id\n";
- mtr_report("MySQL Version $1.$2.$3");
+ mtr_report("MariaDB Version $1.$2.$3");
}
}
else
@@ -1635,7 +1735,6 @@ sub collect_mysqld_features {
}
}
}
- rmtree($tmpdir);
mtr_error("Could not find version of MySQL") unless $mysql_version_id;
mtr_error("Could not find variabes list") unless $found_variable_list_start;
@@ -1720,9 +1819,9 @@ sub executable_setup () {
if ( -x "../libtool")
{
$exe_libtool= "../libtool";
- if ($opt_valgrind or $glob_debugger)
+ if ($opt_valgrind or $glob_debugger or $opt_strace)
{
- mtr_report("Using \"$exe_libtool\" when running valgrind or debugger");
+ mtr_report("Using \"$exe_libtool\" when running valgrind, strace or debugger");
}
}
@@ -1753,8 +1852,7 @@ sub executable_setup () {
if ( $opt_embedded_server )
{
$exe_mysqltest=
- mtr_exe_exists(vs_config_dirs('libmysqld/examples','mysqltest_embedded'),
- "$basedir/libmysqld/examples/mysqltest_embedded",
+ mtr_exe_exists("$basedir/libmysqld/examples$opt_vs_config/mysqltest_embedded",
"$path_client_bindir/mysqltest_embedded");
}
else
@@ -1796,6 +1894,18 @@ sub client_arguments ($;$) {
}
+sub mysqlbinlog_arguments () {
+ my $exe= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
+
+ my $args;
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
+ mtr_add_arg($args, "--local-load=%s", $opt_tmpdir);
+ client_debug_arg($args, "mysqlbinlog");
+ return mtr_args2str($exe, @$args);
+}
+
+
sub mysqlslap_arguments () {
my $exe= mtr_exe_maybe_exists("$path_client_bindir/mysqlslap");
if ( $exe eq "" ) {
@@ -1833,12 +1943,10 @@ sub mysql_client_test_arguments(){
# mysql_client_test executable may _not_ exist
if ( $opt_embedded_server ) {
$exe= mtr_exe_maybe_exists(
- vs_config_dirs('libmysqld/examples','mysql_client_test_embedded'),
- "$basedir/libmysqld/examples/mysql_client_test_embedded",
+ "$basedir/libmysqld/examples$opt_vs_config/mysql_client_test_embedded",
"$basedir/bin/mysql_client_test_embedded");
} else {
- $exe= mtr_exe_maybe_exists(vs_config_dirs('tests', 'mysql_client_test'),
- "$basedir/tests/mysql_client_test",
+ $exe= mtr_exe_maybe_exists("$basedir/tests$opt_vs_config/mysql_client_test",
"$basedir/bin/mysql_client_test");
}
@@ -1855,6 +1963,37 @@ sub mysql_client_test_arguments(){
return mtr_args2str($exe, @$args);
}
+sub tool_arguments ($$) {
+ my($sedir, $tool_name) = @_;
+ my $exe= my_find_bin($basedir,
+ [$sedir, "bin"],
+ $tool_name);
+
+ my $args;
+ mtr_init_args(\$args);
+ client_debug_arg($args, $tool_name);
+ return mtr_args2str($exe, @$args);
+}
+
+# This is not used to actually start a mysqld server, just to allow test
+# scripts to run the mysqld binary to test invalid server startup options.
+sub mysqld_client_arguments () {
+ my $default_mysqld= default_mysqld();
+ my $exe = find_mysqld($basedir);
+ my $args;
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--basedir=%s", $basedir);
+ mtr_add_arg($args, "--character-sets-dir=%s", $default_mysqld->value("character-sets-dir"));
+ mtr_add_arg($args, "--language=%s", $default_mysqld->value("language"));
+ return mtr_args2str($exe, @$args);
+}
+
+
+sub have_maria_support () {
+ my $maria_var= $mysqld_variables{'aria'};
+ return defined $maria_var and $maria_var eq 'TRUE';
+}
#
# Set environment to be used by childs of this process for
@@ -1920,105 +2059,6 @@ sub environment_setup {
}
# --------------------------------------------------------------------------
- # Add the path where mysqld will find udf_example.so
- # --------------------------------------------------------------------------
- my $udf_example_filename;
- if (IS_WINDOWS)
- {
- $udf_example_filename = "udf_example.dll";
- }
- else
- {
- $udf_example_filename = "udf_example.so";
- }
- my $lib_udf_example=
- mtr_file_exists(vs_config_dirs('sql', $udf_example_filename),
- "$basedir/sql/.libs/$udf_example_filename",);
-
- if ( $lib_udf_example )
- {
- push(@ld_library_paths, dirname($lib_udf_example));
- }
-
- $ENV{'UDF_EXAMPLE_LIB'}=
- ($lib_udf_example ? basename($lib_udf_example) : "");
- $ENV{'UDF_EXAMPLE_LIB_OPT'}= "--plugin-dir=".
- ($lib_udf_example ? dirname($lib_udf_example) : "");
-
- # --------------------------------------------------------------------------
- # Add the path where mysqld will find ha_example.so
- # --------------------------------------------------------------------------
- if ($mysql_version_id >= 50100) {
- my ($lib_example_plugin) = find_plugin("ha_example", "storage/example");
-
- if($lib_example_plugin)
- {
- $ENV{'EXAMPLE_PLUGIN'}=
- ($lib_example_plugin ? basename($lib_example_plugin) : "");
- $ENV{'EXAMPLE_PLUGIN_OPT'}= "--plugin-dir=".
- ($lib_example_plugin ? dirname($lib_example_plugin) : "");
-
- $ENV{'HA_EXAMPLE_SO'}="'".basename($lib_example_plugin)."'";
- $ENV{'EXAMPLE_PLUGIN_LOAD'}="--plugin_load=EXAMPLE=".basename($lib_example_plugin);
- }
- else
- {
- # Some ".opt" files use some of these variables, so they must be defined
- $ENV{'EXAMPLE_PLUGIN'}= "";
- $ENV{'EXAMPLE_PLUGIN_OPT'}= "";
- $ENV{'HA_EXAMPLE_SO'}= "";
- $ENV{'EXAMPLE_PLUGIN_LOAD'}= "";
- }
- }
-
-
- # --------------------------------------------------------------------------
- # Add the path where mysqld will find semisync plugins
- # --------------------------------------------------------------------------
- if (!$opt_embedded_server) {
-
-
- my ($lib_semisync_master_plugin) = find_plugin("semisync_master", "plugin/semisync");
- my ($lib_semisync_slave_plugin) = find_plugin("semisync_slave", "plugin/semisync");
-
-
- if ($lib_semisync_master_plugin && $lib_semisync_slave_plugin)
- {
- $ENV{'SEMISYNC_MASTER_PLUGIN'}= basename($lib_semisync_master_plugin);
- $ENV{'SEMISYNC_SLAVE_PLUGIN'}= basename($lib_semisync_slave_plugin);
- $ENV{'SEMISYNC_PLUGIN_OPT'}= "--plugin-dir=".dirname($lib_semisync_master_plugin);
- }
- else
- {
- $ENV{'SEMISYNC_MASTER_PLUGIN'}= "";
- $ENV{'SEMISYNC_SLAVE_PLUGIN'}= "";
- $ENV{'SEMISYNC_PLUGIN_OPT'}="--plugin-dir=";
- }
- }
-
- # ----------------------------------------------------
- # Add the paths where mysqld will find archive/blackhole/federated plugins.
- # ----------------------------------------------------
- $ENV{'ARCHIVE_PLUGIN_DIR'} =
- dirname(find_plugin("ha_archive", "storage/archive"));
- $ENV{'BLACKHOLE_PLUGIN_DIR'} =
- dirname(find_plugin("ha_blackhole", "storage/blackhole"));
- $ENV{'FEDERATED_PLUGIN_DIR'} =
- dirname(find_plugin("ha_federated", "storage/federated"));
-
- # ----------------------------------------------------
- # Add the path where mysqld will find mypluglib.so
- # ----------------------------------------------------
-
- my ($lib_simple_parser) = find_plugin("mypluglib", "plugin/fulltext");
-
- $ENV{'MYPLUGLIB_SO'}="'".basename($lib_simple_parser)."'";
- $ENV{'SIMPLE_PARSER'}=
- ($lib_simple_parser ? basename($lib_simple_parser) : "");
- $ENV{'SIMPLE_PARSER_OPT'}= "--plugin-dir=".
- ($lib_simple_parser ? dirname($lib_simple_parser) : "");
-
- # --------------------------------------------------------------------------
# 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
@@ -2085,6 +2125,15 @@ sub environment_setup {
$ENV{'MYSQL_SHAREDIR'}= $path_language;
$ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir;
+ #
+ # Some stupid^H^H^H^H^H^Hignorant network providers set up "wildcard DNS"
+ # servers that return some given web server address for any lookup of a
+ # non-existent host name. This confuses test cases that want to test the
+ # behaviour when connecting to a non-existing host, so we need to be able
+ # to disable those tests when DNS is broken.
+ #
+ $ENV{HAVE_BROKEN_DNS}= defined(gethostbyname('invalid_hostname'));
+
# ----------------------------------------------------
# Setup env for NDB
# ----------------------------------------------------
@@ -2122,7 +2171,7 @@ sub environment_setup {
$ENV{'MYSQL_SLAP'}= mysqlslap_arguments();
$ENV{'MYSQL_IMPORT'}= client_arguments("mysqlimport");
$ENV{'MYSQL_SHOW'}= client_arguments("mysqlshow");
- $ENV{'MYSQL_BINLOG'}= client_arguments("mysqlbinlog");
+ $ENV{'MYSQL_BINLOG'}= mysqlbinlog_arguments();
$ENV{'MYSQL'}= client_arguments("mysql");
$ENV{'MYSQL_SLAVE'}= client_arguments("mysql", ".2");
$ENV{'MYSQL_UPGRADE'}= client_arguments("mysql_upgrade");
@@ -2135,8 +2184,7 @@ sub environment_setup {
# some versions, test using it should be skipped
# ----------------------------------------------------
my $exe_bug25714=
- mtr_exe_maybe_exists(vs_config_dirs('tests', 'bug25714'),
- "$basedir/tests/bug25714");
+ mtr_exe_maybe_exists("$basedir/tests$opt_vs_config/bug25714");
$ENV{'MYSQL_BUG25714'}= native_path($exe_bug25714);
# ----------------------------------------------------
@@ -2145,6 +2193,7 @@ sub environment_setup {
my $file_mysql_fix_privilege_tables=
mtr_file_exists("$basedir/scripts/mysql_fix_privilege_tables.sql",
"$basedir/share/mysql_fix_privilege_tables.sql",
+ "$basedir/share/mariadb/mysql_fix_privilege_tables.sql",
"$basedir/share/mysql/mysql_fix_privilege_tables.sql");
$ENV{'MYSQL_FIX_PRIVILEGE_TABLES'}= $file_mysql_fix_privilege_tables;
@@ -2152,26 +2201,26 @@ sub environment_setup {
# my_print_defaults
# ----------------------------------------------------
my $exe_my_print_defaults=
- mtr_exe_exists(vs_config_dirs('extra', 'my_print_defaults'),
- "$path_client_bindir/my_print_defaults",
- "$basedir/extra/my_print_defaults");
+ mtr_exe_exists("$basedir/extra$opt_vs_config/my_print_defaults",
+ "$path_client_bindir/my_print_defaults");
$ENV{'MYSQL_MY_PRINT_DEFAULTS'}= native_path($exe_my_print_defaults);
# ----------------------------------------------------
- # Setup env so childs can execute myisampack and myisamchk
+ # myisam tools
+ # ----------------------------------------------------
+ $ENV{'MYISAMLOG'}= tool_arguments("storage/myisam", "myisamlog", );
+ $ENV{'MYISAMCHK'}= tool_arguments("storage/myisam", "myisamchk");
+ $ENV{'MYISAMPACK'}= tool_arguments("storage/myisam", "myisampack");
+ $ENV{'MYISAM_FTDUMP'}= tool_arguments("storage/myisam", "myisam_ftdump");
+
+ # ----------------------------------------------------
+ # aria tools
# ----------------------------------------------------
- $ENV{'MYISAMCHK'}= native_path(mtr_exe_exists(
- vs_config_dirs('storage/myisam', 'myisamchk'),
- vs_config_dirs('myisam', 'myisamchk'),
- "$path_client_bindir/myisamchk",
- "$basedir/storage/myisam/myisamchk",
- "$basedir/myisam/myisamchk"));
- $ENV{'MYISAMPACK'}= native_path(mtr_exe_exists(
- vs_config_dirs('storage/myisam', 'myisampack'),
- vs_config_dirs('myisam', 'myisampack'),
- "$path_client_bindir/myisampack",
- "$basedir/storage/myisam/myisampack",
- "$basedir/myisam/myisampack"));
+ if (have_maria_support())
+ {
+ $ENV{'MARIA_CHK'}= tool_arguments("storage/maria", "aria_chk");
+ $ENV{'MARIA_PACK'}= tool_arguments("storage/maria", "aria_pack");
+ }
# ----------------------------------------------------
# mysqlhotcopy
@@ -2187,8 +2236,7 @@ sub environment_setup {
# ----------------------------------------------------
# perror
# ----------------------------------------------------
- my $exe_perror= mtr_exe_exists(vs_config_dirs('extra', 'perror'),
- "$basedir/extra/perror",
+ my $exe_perror= mtr_exe_exists("$basedir/extra$opt_vs_config/perror",
"$path_client_bindir/perror");
$ENV{'MY_PERROR'}= native_path($exe_perror);
@@ -2292,7 +2340,11 @@ sub remove_stale_vardir () {
rmtree("$opt_tmpdir/");
}
-
+sub set_plugin_var($) {
+ local $_ = $_[0];
+ s/\.\w+$//;
+ $ENV{"\U${_}_SO"} = $_[0];
+}
#
# Create var and the directories needed in var
@@ -2357,6 +2409,44 @@ sub setup_vardir() {
# and make them world readable
copytree("$glob_mysql_test_dir/std_data", "$opt_vardir/std_data", "0022");
+ # create a plugin dir and copy plugins into it
+ if ($source_dist)
+ {
+ $plugindir="$opt_vardir/plugins";
+ unshift (@opt_extra_mysqld_opt, "--plugin-dir=$plugindir");
+ mkpath($plugindir);
+ if (IS_WINDOWS)
+ {
+ for (<../storage/*$opt_vs_config/*.dll>,
+ <../plugin/*$opt_vs_config/*.dll>,
+ <../sql$opt_vs_config/*.dll>)
+ {
+ my $pname=basename($_);
+ copy rel2abs($_), "$plugindir/$pname";
+ set_plugin_var($pname);
+ }
+ }
+ else
+ {
+ for (<../storage/*/.libs/*.so>,<../plugin/*/.libs/*.so>,<../sql/.libs/*.so>)
+ {
+ my $pname=basename($_);
+ symlink rel2abs($_), "$plugindir/$pname";
+ set_plugin_var($pname);
+ }
+ }
+ }
+ else
+ {
+ # hm, what paths work for debs and for rpms ?
+ for (<$basedir/lib/mysql/plugin/*.so>,
+ <$basedir/lib/plugin/*.dll>)
+ {
+ my $pname=basename($_);
+ set_plugin_var($pname);
+ }
+ }
+
# Remove old log files
foreach my $name (glob("r/*.progress r/*.log r/*.warnings"))
{
@@ -2391,7 +2481,7 @@ sub check_running_as_root () {
{
mtr_warning("running this script as _root_ will cause some " .
"tests to be skipped");
- $ENV{'MYSQL_TEST_ROOT'}= "YES";
+ $ENV{'MYSQL_TEST_ROOT'}= "1";
}
chmod(oct("0755"), $test_file);
@@ -2447,26 +2537,36 @@ sub check_debug_support ($) {
#
-# Helper function to handle configuration-based subdirectories which Visual
-# Studio uses for storing binaries. If opt_vs_config is set, this returns
-# a path based on that setting; if not, it returns paths for the default
-# /release/ and /debug/ subdirectories.
+# Helper function to find the correct value for the opt_vs_config
+# if it was not set explicitly.
+#
+# the configuration with the most recent build dir in sql/ is selected.
#
-# $exe can be undefined, if the directory itself will be used
+# note: looking for all BuildLog.htm files everywhere in the tree with the
+# help of File::Find would be possibly more precise, but it is also
+# many times slower. Thus we are only looking at the server, client
+# executables, and plugins - that is, something that can affect the test suite
#
-sub vs_config_dirs ($$) {
- my ($path_part, $exe) = @_;
+sub fix_vs_config_dir () {
+ return $opt_vs_config="" unless IS_WINDOWS;
+ return $opt_vs_config="/$opt_vs_config" if $opt_vs_config;
- $exe = "" if not defined $exe;
- if ($opt_vs_config)
- {
- return ("$bindir/$path_part/$opt_vs_config/$exe");
+ my $modified = 1e30;
+ $opt_vs_config="";
+
+ for my $dir (qw(client/*.dir libmysql/libmysql.dir sql/mysqld.dir
+ sql/udf_example.dir storage/*/*.dir plugin/*/*.dir)) {
+ for (<$basedir/$dir/*/BuildLog.htm>) {
+ if (-M $_ < $modified)
+ {
+ $modified = -M _;
+ $opt_vs_config = basename(dirname($_));
+ }
+ }
}
- return ("$bindir/$path_part/Release/$exe",
- "$bindir/$path_part/RelWithDebinfo/$exe",
- "$bindir/$path_part/Debug/$exe",
- "$bindir/$path_part/$exe");
+ mtr_report("VS config: $opt_vs_config");
+ $opt_vs_config="/$opt_vs_config" if $opt_vs_config;
}
@@ -2486,7 +2586,7 @@ sub check_ndbcluster_support ($) {
if ( ! $mysqld_variables{'ndb-connectstring'} )
{
- mtr_report(" - skipping ndbcluster, mysqld not compiled with ndbcluster");
+ #mtr_report(" - skipping ndbcluster, mysqld not compiled with ndbcluster");
$opt_skip_ndbcluster= 2;
return;
}
@@ -2497,7 +2597,7 @@ sub check_ndbcluster_support ($) {
}
-sub ndbcluster_wait_started($$){
+sub ndbcluster_wait_started {
my $cluster= shift;
my $ndb_waiter_extra_opt= shift;
my $path_waitlog= join('/', $opt_vardir, $cluster->name(), "ndb_waiter.log");
@@ -2665,7 +2765,7 @@ sub ndbd_start {
sub ndbcluster_start ($) {
- my $cluster= shift;
+ my ($cluster) = @_;
mtr_verbose("ndbcluster_start '".$cluster->name()."'");
@@ -2685,6 +2785,109 @@ sub ndbcluster_start ($) {
}
+sub mysql_server_start($) {
+ my ($mysqld, $tinfo) = @_;
+
+ if ( $mysqld->{proc} )
+ {
+ # Already started
+
+ # Write start of testcase to log file
+ mark_log($mysqld->value('#log-error'), $tinfo);
+
+ return;
+ }
+
+ my $datadir= $mysqld->value('datadir');
+ if (not $opt_start_dirty)
+ {
+
+ my @options= ('log-bin', 'relay-log');
+ foreach my $option_name ( @options ) {
+ next unless $mysqld->option($option_name);
+
+ my $file_name= $mysqld->value($option_name);
+ next unless
+ defined $file_name and
+ -e $file_name;
+
+ mtr_debug(" -removing '$file_name'");
+ unlink($file_name) or die ("unable to remove file '$file_name'");
+ }
+
+ if (-d $datadir ) {
+ preserve_error_log($mysqld);
+ mtr_verbose(" - removing '$datadir'");
+ rmtree($datadir);
+ }
+ }
+
+ my $mysqld_basedir= $mysqld->value('basedir');
+ if ( $basedir eq $mysqld_basedir )
+ {
+ if (! $opt_start_dirty) # If dirty, keep possibly grown system db
+ {
+ # Copy datadir from installed system db
+ for my $path ( "$opt_vardir", "$opt_vardir/..") {
+ my $install_db= "$path/install.db";
+ copytree($install_db, $datadir)
+ if -d $install_db;
+ }
+ mtr_error("Failed to copy system db to '$datadir'")
+ unless -d $datadir;
+ }
+ }
+ else
+ {
+ mysql_install_db($mysqld); # For versional testing
+
+ mtr_error("Failed to install system db to '$datadir'")
+ unless -d $datadir;
+
+ }
+ restore_error_log($mysqld);
+
+ # Create the servers tmpdir
+ my $tmpdir= $mysqld->value('tmpdir');
+ mkpath($tmpdir) unless -d $tmpdir;
+
+ # Write start of testcase to log file
+ mark_log($mysqld->value('#log-error'), $tinfo);
+
+ # Run <tname>-master.sh
+ if ($mysqld->option('#!run-master-sh') and
+ run_sh_script($tinfo->{master_sh}) )
+ {
+ $tinfo->{'comment'}= "Failed to execute '$tinfo->{master_sh}'";
+ return 1;
+ }
+
+ # Run <tname>-slave.sh
+ if ($mysqld->option('#!run-slave-sh') and
+ run_sh_script($tinfo->{slave_sh}))
+ {
+ $tinfo->{'comment'}= "Failed to execute '$tinfo->{slave_sh}'";
+ return 1;
+ }
+
+ if (!$opt_embedded_server)
+ {
+ my $extra_opts= get_extra_opts($mysqld, $tinfo);
+ mysqld_start($mysqld,$extra_opts);
+
+ # Save this test case information, so next can examine it
+ $mysqld->{'started_tinfo'}= $tinfo;
+ }
+}
+
+sub mysql_server_wait {
+ my ($mysqld) = @_;
+
+ return not sleep_until_file_created($mysqld->value('pid-file'),
+ $opt_start_timeout,
+ $mysqld->{'proc'});
+}
+
sub create_config_file_for_extern {
my %opts=
(
@@ -2908,8 +3111,13 @@ sub mysql_install_db {
mtr_add_arg($args, "--bootstrap");
mtr_add_arg($args, "--basedir=%s", $install_basedir);
mtr_add_arg($args, "--datadir=%s", $install_datadir);
- mtr_add_arg($args, "--loose-skip-falcon");
+ mtr_add_arg($args, "--default-storage-engine=myisam");
+ mtr_add_arg($args, "--loose-skip-innodb");
+ mtr_add_arg($args, "--loose-skip-pbxt");
mtr_add_arg($args, "--loose-skip-ndbcluster");
+ mtr_add_arg($args, "--loose-skip-aria");
+ mtr_add_arg($args, "--disable-sync-frm");
+ mtr_add_arg($args, "--loose-disable-debug");
mtr_add_arg($args, "--tmpdir=%s", "$opt_vardir/tmp/");
mtr_add_arg($args, "--core-file");
@@ -2939,6 +3147,12 @@ sub mysql_install_db {
my $exe_mysqld_bootstrap =
$ENV{'MYSQLD_BOOTSTRAP'} || find_mysqld($install_basedir);
+ # MASV add only to bootstrap.test
+ # Setup args for bootstrap.test
+ #
+ #mtr_init_args(\$cmd_args);
+ #mtr_add_arg($cmd_args, "--loose-skip-aria")
+
# ----------------------------------------------------------------------
# export MYSQLD_BOOTSTRAP_CMD variable containing <path>/mysqld <args>
# ----------------------------------------------------------------------
@@ -2952,8 +3166,8 @@ sub mysql_install_db {
my $bootstrap_sql_file= "$opt_vardir/tmp/bootstrap.sql";
my $path_sql= my_find_file($install_basedir,
- ["mysql", "sql/share", "share/mysql",
- "share", "scripts"],
+ ["mysql", "sql/share", "share/mariadb",
+ "share/mysql", "share", "scripts"],
"mysql_system_tables.sql",
NOT_REQUIRED);
@@ -3048,6 +3262,26 @@ sub run_testcase_check_skip_test($)
my ($tinfo)= @_;
# ----------------------------------------------------------------------
+ # Skip some tests silently
+ # ----------------------------------------------------------------------
+
+ my $start_from= $mtr_cases::start_from;
+ if ( $start_from )
+ {
+ if ($tinfo->{'name'} eq $start_from ||
+ $tinfo->{'shortname'} eq $start_from)
+ {
+ ## Found parting test. Run this test and all tests after this one
+ $mtr_cases::start_from= "";
+ }
+ else
+ {
+ $tinfo->{'result'}= 'MTR_RES_SKIPPED';
+ return 1;
+ }
+ }
+
+ # ----------------------------------------------------------------------
# If marked to skip, just print out and return.
# Note that a test case not marked as 'skip' can still be
# skipped later, because of the test case itself in cooperation
@@ -3204,9 +3438,13 @@ test case was executed:\n";
$result= 2;
}
-
- # Remove the .result file the check generated
- unlink("$base_file.result");
+ else
+ {
+ # Remove the .result file the check generated
+ unlink("$base_file.result");
+ }
+ # Remove the .err file the check generated
+ unlink($err_file);
}
}
@@ -3349,6 +3587,7 @@ sub run_on_all($$)
sub mark_log {
my ($log, $tinfo)= @_;
my $log_msg= "CURRENT_TEST: $tinfo->{name}\n";
+ pre_write_errorlog($log, $tinfo->{name});
mtr_tofile($log, $log_msg);
}
@@ -3426,9 +3665,83 @@ sub restart_forced_by_test
# Return timezone value of tinfo or default value
sub timezone {
my ($tinfo)= @_;
- return $tinfo->{timezone} || "GMT-3";
+ local $_ = $tinfo->{timezone};
+ return 'DEFAULT' unless defined $_;
+ no warnings 'uninitialized';
+ s/\$\{(\w+)\}/$ENV{$1}/ge;
+ s/\$(\w+)/$ENV{$1}/ge;
+ $_;
+}
+
+sub mycnf_create {
+ my ($config) = @_;
+ my $res;
+
+ foreach my $group ($config->groups()) {
+ $res .= "[$group->{name}]\n";
+
+ foreach my $option ($group->options()) {
+ $res .= $option->name();
+ my $value= $option->value();
+ if (defined $value) {
+ $res .= "=$value";
+ }
+ $res .= "\n";
+ }
+ $res .= "\n";
+ }
+ $res;
}
+sub config_files($) {
+ my ($tinfo) = @_;
+ (
+ 'my.cnf' => \&mycnf_create,
+ $suites{$tinfo->{suite}}->config_files()
+ );
+}
+
+sub _like { return $config ? $config->like($_[0]) : (); }
+sub mysqlds { return _like('mysqld\.'); }
+sub ndbds { return _like('cluster_config\.ndbd\.');}
+sub ndb_mgmds { return _like('cluster_config\.ndb_mgmd\.'); }
+
+sub fix_servers($) {
+ my ($tinfo) = @_;
+ return () unless $config;
+ my %servers = (
+ qr/mysqld\./ => {
+ SORT => 300,
+ START => \&mysql_server_start,
+ WAIT => \&mysql_server_wait,
+ },
+ qr/mysql_cluster\./ => {
+ SORT => 200,
+ START => \&ndbcluster_start,
+ WAIT => \&ndbcluster_wait_started,
+ },
+ qr/cluster_config\.ndb_mgmd\./ => {
+ SORT => 210,
+ START => undef,
+ },
+ qr/cluster_config\.ndbd\./ => {
+ SORT => 220,
+ START => undef,
+ },
+ $suites{$tinfo->{suite}}->servers()
+ );
+ for ($config->groups()) {
+ while (my ($re,$prop) = each %servers) {
+ @$_{keys %$prop} = values %$prop if $_->{name} =~ /^$re/;
+ }
+ }
+}
+
+sub all_servers {
+ return unless $config;
+ ( sort { $a->{SORT} <=> $b->{SORT} }
+ grep { defined $_->{SORT} } $config->groups() );
+}
# Storage for changed environment variables
my %old_env;
@@ -3441,8 +3754,8 @@ my %old_env;
# > 0 failure
#
-sub run_testcase ($) {
- my $tinfo= shift;
+sub run_testcase ($$) {
+ my ($tinfo, $server_socket)= @_;
mtr_verbose("Running test:", $tinfo->{name});
@@ -3458,14 +3771,23 @@ sub run_testcase ($) {
# Init variables that can change between each test case
# -------------------------------------------------------
my $timezone= timezone($tinfo);
- $ENV{'TZ'}= $timezone;
+ if ($timezone ne 'DEFAULT') {
+ $ENV{'TZ'}= $timezone;
+ } else {
+ delete($ENV{'TZ'});
+ }
mtr_verbose("Setting timezone: $timezone");
if ( ! using_extern() )
{
my @restart= servers_need_restart($tinfo);
if ( @restart != 0) {
- stop_servers($tinfo, @restart );
+ # Remember that we restarted for this test case (count restarts)
+ $tinfo->{'restarted'}= 1;
+ stop_servers(reverse @restart);
+ if ($opt_warnings) {
+ check_warnings_post_shutdown($server_socket);
+ }
}
if ( started(all_servers()) == 0 )
@@ -3499,7 +3821,6 @@ sub run_testcase ($) {
vardir => $opt_vardir,
tmpdir => $opt_tmpdir,
baseport => $baseport,
- #hosts => [ 'host1', 'host2' ],
user => $opt_user,
password => '',
ssl => $opt_ssl_supported,
@@ -3507,8 +3828,16 @@ sub run_testcase ($) {
}
);
- # Write the new my.cnf
- $config->save($path_config_file);
+ fix_servers($tinfo);
+
+ # Write config files:
+ my %config_files = config_files($tinfo);
+ while (my ($file, $generate) = each %config_files) {
+ my ($path) = "$opt_vardir/$file";
+ open (F, '>', $path) or die "Could not open '$path': $!";
+ print F &$generate($config);
+ close F;
+ }
# Remember current config so a restart can occur when a test need
# to use a different one
@@ -3530,6 +3859,11 @@ sub run_testcase ($) {
# Write start of testcase to log
mark_log($path_current_testlog, $tinfo);
+ # Make sure the safe_process also exits from now on
+ if ($opt_start_exit) {
+ My::SafeProcess->start_exit();
+ }
+
if (start_servers($tinfo))
{
report_failure_and_restart($tinfo);
@@ -3660,7 +3994,18 @@ sub run_testcase ($) {
{
if ($check_res == 1) {
# Test case had sideeffects, not fatal error, just continue
- stop_all_servers($opt_shutdown_timeout);
+ if ($opt_warnings) {
+ # Checking error logs for warnings, so need to stop server
+ # gracefully so that memory leaks etc. can be properly detected.
+ stop_servers(reverse all_servers());
+ check_warnings_post_shutdown($server_socket);
+ # Even if we got warnings here, we should not fail this
+ # particular test, as the warnings may be caused by an earlier
+ # test.
+ } else {
+ # Not checking warnings, so can do a hard shutdown.
+ stop_all_servers($opt_shutdown_timeout);
+ }
mtr_report("Resuming tests...\n");
}
else {
@@ -3809,15 +4154,76 @@ sub run_testcase ($) {
}
+# We want to preserve the error log between server restarts, as it may contain
+# valuable debugging information even if there is no test failure recorded.
+sub _preserve_error_log_names {
+ my ($mysqld)= @_;
+ my $error_log_file= $mysqld->if_exist('#log-error');
+ return (undef, undef) unless $error_log_file;
+ my $error_log_dir= dirname($error_log_file);
+ my $save_name= $error_log_dir ."/../". $mysqld->name() .".error.log";
+ return ($error_log_file, $save_name);
+}
+
+sub preserve_error_log {
+ my ($mysqld)= @_;
+ my ($error_log_file, $save_name)= _preserve_error_log_names($mysqld);
+ rename($error_log_file, $save_name) if $save_name;
+ # Ignore any errors, as it's just a best-effort to keep the log if possible.
+}
+
+sub restore_error_log {
+ my ($mysqld)= @_;
+ my ($error_log_file, $save_name)= _preserve_error_log_names($mysqld);
+ rename($save_name, $error_log_file) if $save_name;
+}
+
+# Keep track of last position in mysqld error log where we scanned for
+# warnings, so we can attribute any warnings found to the correct test
+# suite or server restart.
+my $last_warning_position= { };
+
+# Called just before a mysqld server is started or a testcase is run,
+# to keep track of which tests have been run since last restart, and
+# of when the error log is reset.
+#
+# Second argument $test_name is test name, or undef for server restart.
+sub pre_write_errorlog {
+ my ($error_log, $test_name)= @_;
+
+ if (! -e $error_log) {
+ # If the error log is moved away, reset the warning parse position.
+ delete $last_warning_position->{$error_log};
+ }
+
+ if (defined($test_name)) {
+ $last_warning_position->{$error_log}{test_names}= []
+ unless exists($last_warning_position->{$error_log}{test_names});
+ push @{$last_warning_position->{$error_log}{test_names}}, $test_name;
+ } else {
+ # Server restart, so clear the list of tests run since last restart.
+ # (except the last one (if any), which is the test about to be run).
+ if (defined($last_warning_position->{$error_log}{test_names}) &&
+ @{$last_warning_position->{$error_log}{test_names}}) {
+ $last_warning_position->{$error_log}{test_names}=
+ [$last_warning_position->{$error_log}{test_names}[-1]];
+ } else {
+ $last_warning_position->{$error_log}{test_names}= [];
+ }
+ }
+}
+
# Extract server log from after the last occurrence of named test
# Return as an array of lines
#
sub extract_server_log ($$) {
my ($error_log, $tname) = @_;
+
+ return unless $error_log;
# Open the servers .err log file and read all lines
- # belonging to current tets into @lines
+ # belonging to current test into @lines
my $Ferr = IO::File->new($error_log)
or mtr_error("Could not open file '$error_log' for reading: $!");
@@ -3857,9 +4263,9 @@ sub get_log_from_proc ($$) {
my ($proc, $name)= @_;
my $srv_log= "";
- foreach my $mysqld (mysqlds()) {
+ foreach my $mysqld (all_servers()) {
if ($mysqld->{proc} eq $proc) {
- my @srv_lines= extract_server_log($mysqld->value('#log-error'), $name);
+ my @srv_lines= extract_server_log($mysqld->if_exist('#log-error'), $name);
$srv_log= "\nServer log from this test:\n" . join ("", @srv_lines);
last;
}
@@ -3867,16 +4273,48 @@ sub get_log_from_proc ($$) {
return $srv_log;
}
+#
# Perform a rough examination of the servers
# error log and write all lines that look
# suspicious into $error_log.warnings
#
-sub extract_warning_lines ($$) {
- my ($error_log, $tname) = @_;
+sub extract_warning_lines ($) {
+ my ($error_log) = @_;
+
+ # Open the servers .err log file and read all lines
+ # belonging to current tets into @lines
+ my $Ferr = IO::File->new($error_log)
+ or return [];
+ my $last_pos= $last_warning_position->{$error_log}{seek_pos};
+ $Ferr->seek($last_pos, 0) if defined($last_pos);
+ # If the seek fails, we will parse the whole error log, at least we will not
+ # miss any warnings.
+
+ my @lines= <$Ferr>;
+ $last_warning_position->{$error_log}{seek_pos}= $Ferr->tell();
+ $Ferr = undef; # Close error log file
+
+ # mysql_client_test.test sends a COM_DEBUG packet to the server
+ # to provoke a SAFEMALLOC leak report, ignore any warnings
+ # between "Begin/end safemalloc memory dump"
+ if ( grep(/Begin safemalloc memory dump:/, @lines) > 0)
+ {
+ my $discard_lines= 1;
+ foreach my $line ( @lines )
+ {
+ if ($line =~ /Begin safemalloc memory dump:/){
+ $discard_lines = 1;
+ } elsif ($line =~ /End safemalloc memory dump./){
+ $discard_lines = 0;
+ }
- my @lines= extract_server_log($error_log, $tname);
+ if ($discard_lines){
+ $line = "ignored";
+ }
+ }
+ }
-# Write all suspicious lines to $error_log.warnings file
+ # Write all suspicious lines to $error_log.warnings file
my $warning_log = "$error_log.warnings";
my $Fwarn = IO::File->new($warning_log, "w")
or die("Could not open file '$warning_log' for writing: $!");
@@ -3893,29 +4331,79 @@ sub extract_warning_lines ($$) {
qr/Attempting backtrace/,
qr/Assertion .* failed/,
);
- my $skip_valgrind= 0;
+ # These are taken from the include/mtr_warnings.sql global suppression
+ # list. They occur delayed, so they can be parsed during shutdown rather
+ # than during the per-test check.
+ #
+ # ToDo: having the warning suppressions inside the mysqld we are trying to
+ # check is in any case horrible. We should change it to all be done here
+ # within the Perl code, which is both simpler, easier, faster, and more
+ # robust. We could still have individual test cases put in suppressions by
+ # parsing statically or by writing dynamically to a CSV table read by the
+ # Perl code.
+ my @antipatterns =
+ (
+ qr/error .*connecting to master/,
+ qr/Plugin 'ndbcluster' will be forced to shutdown/,
+ qr/InnoDB: Error: in ALTER TABLE `test`.`t[12]`/,
+ qr/InnoDB: Error: table `test`.`t[12]` does not exist in the InnoDB internal/,
+ qr/Slave: Unknown table 't1' Error_code: 1051/,
+ qr/Slave SQL:.*(Error_code: [[:digit:]]+|Query:.*)/,
+ qr/slave SQL thread aborted/,
+ qr/unknown option '--loose[-_]/,
+ qr/unknown variable 'loose[-_]/,
+ qr/Invalid .*old.* table or database name/,
+ qr/Now setting lower_case_table_names to [02]/,
+ qr/Setting lower_case_table_names=2/,
+ qr/You have forced lower_case_table_names to 0/,
+ qr/Plugin 'ndbcluster' will be forced to shutdow/,
+ qr/deprecated/,
+ qr/Slave SQL thread retried transaction/,
+ qr/Slave \(additional info\)/,
+ qr/Incorrect information in file/,
+ qr/Incorrect key file for table .*crashed.*/,
+ qr/Slave I\/O: Get master SERVER_ID failed with error:.*/,
+ qr/Slave I\/O: Get master clock failed with error:.*/,
+ qr/Slave I\/O: Get master COLLATION_SERVER failed with error:.*/,
+ qr/Slave I\/O: Get master TIME_ZONE failed with error:.*/,
+ qr/Slave I\/O: error reconnecting to master '.*' - retry-time: [1-3] retries/,
+ qr/Slave I\/0: Master command COM_BINLOG_DUMP failed/,
+ qr/Error reading packet/,
+ qr/Lost connection to MySQL server at 'reading initial communication packet'/,
+ qr/Failed on request_dump/,
+ qr/Slave: Can't drop database.* database doesn't exist/,
+ qr/Slave: Operation DROP USER failed for 'create_rout_db'/,
+ qr|Checking table: '\./mtr/test_suppressions'|,
+ qr|Table \./test/bug53592 has a primary key in InnoDB data dictionary, but not in MySQL|,
+ qr|mysqld: Table '\./mtr/test_suppressions' is marked as crashed and should be repaired|,
+ qr|InnoDB: Error: table 'test/bug39438'|,
+ );
- foreach my $line ( @lines )
+ my $matched_lines= [];
+ LINE: foreach my $line ( @lines )
{
- if ($opt_valgrind_mysqld) {
- # Skip valgrind summary from tests where server has been restarted
- # Should this contain memory leaks, the final report will find it
- # Use a generic pattern for summaries
- $skip_valgrind= 1 if $line =~ /^==\d+== [A-Z ]+ SUMMARY:/;
- $skip_valgrind= 0 unless $line =~ /^==\d+==/;
- next if $skip_valgrind;
- }
- foreach my $pat ( @patterns )
+ PAT: foreach my $pat ( @patterns )
{
if ( $line =~ /$pat/ )
{
+ foreach my $apat (@antipatterns)
+ {
+ next LINE if $line =~ $apat;
+ }
print $Fwarn $line;
- last;
+ push @$matched_lines, $line;
+ last PAT;
}
}
}
$Fwarn = undef; # Close file
+ if (scalar(@$matched_lines) > 0 &&
+ defined($last_warning_position->{$error_log}{test_names})) {
+ return ($last_warning_position->{$error_log}{test_names}, $matched_lines);
+ } else {
+ return ([], $matched_lines);
+ }
}
@@ -3934,7 +4422,7 @@ sub start_check_warnings ($$) {
my $log_error= $mysqld->value('#log-error');
# To be communicated to the test
$ENV{MTR_LOG_ERROR}= $log_error;
- extract_warning_lines($log_error, $tinfo->{name});
+ extract_warning_lines($log_error);
my $args;
mtr_init_args(\$args);
@@ -3968,7 +4456,7 @@ sub start_check_warnings ($$) {
error => $errfile,
output => $errfile,
args => \$args,
- user_data => $errfile,
+ user_data => [$errfile, $mysqld],
verbose => $opt_verbose,
);
mtr_verbose("Started $proc");
@@ -3978,7 +4466,7 @@ sub start_check_warnings ($$) {
#
# Loop through our list of processes and check the error log
-# for unexepcted errors and warnings
+# for unexpected errors and warnings
#
sub check_warnings ($) {
my ($tinfo)= @_;
@@ -4014,7 +4502,7 @@ sub check_warnings ($) {
if ( delete $started{$proc->pid()} ) {
# One check warning process returned
my $res= $proc->exit_status();
- my $err_file= $proc->user_data();
+ my ($err_file, $mysqld)= @{$proc->user_data()};
if ( $res == 0 or $res == 62 ){
@@ -4047,7 +4535,8 @@ sub check_warnings ($) {
my $report= mtr_grab_file($err_file);
$tinfo->{comment}.=
"Could not execute 'check-warnings' for ".
- "testcase '$tname' (res: $res):\n";
+ "testcase '$tname' (res: $res) server: '".
+ $mysqld->name() .":\n";
$tinfo->{comment}.= $report;
$result= 2;
@@ -4075,6 +4564,28 @@ sub check_warnings ($) {
mtr_error("INTERNAL_ERROR: check_warnings");
}
+# Check for warnings generated during shutdown of a mysqld server.
+# If any, report them to master server, and return true; else just return
+# false.
+
+sub check_warnings_post_shutdown {
+ my ($server_socket)= @_;
+ my $testname_hash= { };
+ my $report= '';
+ foreach my $mysqld ( mysqlds())
+ {
+ my ($testlist, $match_lines)=
+ extract_warning_lines($mysqld->value('#log-error'));
+ $testname_hash->{$_}= 1 for @$testlist;
+ $report.= join('', @$match_lines);
+ }
+ my @warning_tests= keys(%$testname_hash);
+ if (@warning_tests) {
+ my $fake_test= My::Test->new(testnames => \@warning_tests);
+ $fake_test->{'warnings'}= $report;
+ $fake_test->write_test($server_socket, 'WARNINGS');
+ }
+}
#
# Loop through our list of processes and look for and entry
@@ -4164,28 +4675,18 @@ sub clean_dir {
sub clean_datadir {
-
mtr_verbose("Cleaning datadirs...");
if (started(all_servers()) != 0){
mtr_error("Trying to clean datadir before all servers stopped");
}
- foreach my $cluster ( clusters() )
+ for (all_servers())
{
- my $cluster_dir= "$opt_vardir/".$cluster->{name};
- mtr_verbose(" - removing '$cluster_dir'");
- rmtree($cluster_dir);
-
- }
-
- foreach my $mysqld ( mysqlds() )
- {
- my $mysqld_dir= dirname($mysqld->value('datadir'));
- if (-d $mysqld_dir ) {
- mtr_verbose(" - removing '$mysqld_dir'");
- rmtree($mysqld_dir);
- }
+ preserve_error_log($_); # or at least, try to
+ my $dir= "$opt_vardir/".$_->{name};
+ mtr_verbose(" - removing '$dir'");
+ rmtree($dir);
}
# Remove all files in tmp and var/tmp
@@ -4208,17 +4709,6 @@ sub save_datadir_after_failure($$) {
}
-sub remove_ndbfs_from_ndbd_datadir {
- my ($ndbd_datadir)= @_;
- # Remove the ndb_*_fs directory from ndbd.X/ dir
- foreach my $ndbfs_dir ( glob("$ndbd_datadir/ndb_*_fs") )
- {
- next unless -d $ndbfs_dir; # Skip if not a directory
- rmtree($ndbfs_dir);
- }
-}
-
-
sub after_failure ($) {
my ($tinfo)= @_;
@@ -4235,31 +4725,18 @@ sub after_failure ($) {
mkpath($save_dir) if ! -d $save_dir;
- # Save the used my.cnf file
- copy($path_config_file, $save_dir);
+ # Save the used config files
+ my %config_files = config_files($tinfo);
+ while (my ($file, $generate) = each %config_files) {
+ copy("$opt_vardir/$file", $save_dir);
+ }
# Copy the tmp dir
copytree("$opt_vardir/tmp/", "$save_dir/tmp/");
- if ( clusters() ) {
- foreach my $cluster ( clusters() ) {
- my $cluster_dir= "$opt_vardir/".$cluster->{name};
-
- # Remove the fileystem of each ndbd
- foreach my $ndbd ( in_cluster($cluster, ndbds()) )
- {
- my $ndbd_datadir= $ndbd->value("DataDir");
- remove_ndbfs_from_ndbd_datadir($ndbd_datadir);
- }
-
- save_datadir_after_failure($cluster_dir, $save_dir);
- }
- }
- else {
- foreach my $mysqld ( mysqlds() ) {
- my $data_dir= $mysqld->value('datadir');
- save_datadir_after_failure(dirname($data_dir), $save_dir);
- }
+ foreach (all_servers()) {
+ my $dir= "$opt_vardir/".$_->{name};
+ save_datadir_after_failure($dir, $save_dir);
}
}
@@ -4358,7 +4835,7 @@ sub mysqld_stop {
name => "mysqladmin shutdown ".$mysqld->name(),
path => $exe_mysqladmin,
args => \$args,
- error => "/dev/null",
+ error => "$opt_vardir/log/mysqladmin.err",
);
}
@@ -4387,14 +4864,16 @@ sub mysqld_arguments ($$$) {
}
}
- if ( $mysql_version_id >= 50106 && !$opt_user_args)
+ mtr_add_arg($args, "%s--disable-sync-frm");
+
+ if (!using_extern() and $mysql_version_id >= 50106 && !$opt_user_args)
{
- # Turn on logging to file
- mtr_add_arg($args, "--log-output=file");
+ # Turn on logging to file and tables
+ mtr_add_arg($args, "%s--log-output=table,file");
}
- # Check if "extra_opt" contains skip-log-bin
- my $skip_binlog= grep(/^(--|--loose-)skip-log-bin/, @$extra_opts);
+ # Check if "extra_opt" contains --log-bin
+ my $skip_binlog= not grep /^--(loose-)?log-bin/, @$extra_opts;
# Indicate to mysqld it will be debugged in debugger
if ( $glob_debugger )
@@ -4464,6 +4943,10 @@ sub mysqld_start ($$) {
{
valgrind_arguments($args, \$exe);
}
+ if ( $opt_strace)
+ {
+ strace_arguments($args, \$exe, $mysqld->name());
+ }
mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));
@@ -4483,7 +4966,9 @@ sub mysqld_start ($$) {
if (IS_WINDOWS)
{
# Trick the server to send output to stderr, with --console
- mtr_add_arg($args, "--console");
+ if (!(grep(/^--log-error/, @$args))) {
+ mtr_add_arg($args, "--console");
+ }
}
if ( $opt_gdb || $opt_manual_gdb )
@@ -4524,7 +5009,17 @@ sub mysqld_start ($$) {
# When both --valgrind and --debug is selected, send
# all output to the trace file, making it possible to
# see the exact location where valgrind complains
- $output= "$opt_vardir/log/".$mysqld->name().".trace";
+
+ # Write a message about this to the normal log file
+ my $trace_name= "$opt_vardir/log/".$mysqld->name().".trace";
+ mtr_tofile($output,
+ "NOTE: When running with --valgrind --debug the output from",
+ "mysqld(where the valgrind messages shows up) is stored ",
+ "together with the trace file to make it ",
+ "easier to find the exact position of valgrind errors.",
+ "See trace file $trace_name.\n");
+ $output= $trace_name;
+
}
# Remember this log file for valgrind error report search
$mysqld_logs{$output}= 1 if $opt_valgrind;
@@ -4533,6 +5028,7 @@ sub mysqld_start ($$) {
if ( defined $exe )
{
+ pre_write_errorlog($output);
$mysqld->{'proc'}= My::SafeProcess->new
(
name => $mysqld->name(),
@@ -4649,8 +5145,7 @@ sub server_need_restart {
return 1;
}
- my $is_mysqld= grep ($server eq $_, mysqlds());
- if ($is_mysqld)
+ if ($server->name() =~ /^mysqld\./)
{
# Check that running process was started with same options
@@ -4705,17 +5200,9 @@ sub servers_need_restart($) {
-#
-# Return list of specific servers
-# - there is no servers in an empty config
-#
-sub _like { return $config ? $config->like($_[0]) : (); }
-sub mysqlds { return _like('mysqld.'); }
-sub ndbds { return _like('cluster_config.ndbd.');}
-sub ndb_mgmds { return _like('cluster_config.ndb_mgmd.'); }
-sub clusters { return _like('mysql_cluster.'); }
-sub all_servers { return ( mysqlds(), ndb_mgmds(), ndbds() ); }
+############################################
+############################################
#
# Filter a list of servers and return only those that are part
@@ -4737,18 +5224,6 @@ sub started { return grep(defined $_, map($_->{proc}, @_)); }
sub stopped { return grep(!defined $_, map($_->{proc}, @_)); }
-sub envsubst {
- my $string= shift;
-
- if ( ! defined $ENV{$string} )
- {
- mtr_error(".opt file references '$string' which is not set");
- }
-
- return $ENV{$string};
-}
-
-
sub get_extra_opts {
# No extra options if --user-args
return \@opt_extra_mysqld_opt if $opt_user_args;
@@ -4762,41 +5237,21 @@ sub get_extra_opts {
# Expand environment variables
foreach my $opt ( @$opts )
{
- $opt =~ s/\$\{(\w+)\}/envsubst($1)/ge;
- $opt =~ s/\$(\w+)/envsubst($1)/ge;
+ no warnings 'uninitialized';
+ $opt =~ s/\$\{(\w+)\}/$ENV{$1}/ge;
+ $opt =~ s/\$(\w+)/$ENV{$1}/ge;
}
return $opts;
}
sub stop_servers($$) {
- my ($tinfo, @servers)= @_;
-
- # Remember if we restarted for this test case (count restarts)
- $tinfo->{'restarted'}= 1;
-
- if ( join('|', @servers) eq join('|', all_servers()) )
- {
- # All servers are going down, use some kind of order to
- # avoid too many warnings in the log files
-
- mtr_report("Restarting all servers");
+ my (@servers)= @_;
- # mysqld processes
- My::SafeProcess::shutdown( $opt_shutdown_timeout, started(mysqlds()) );
-
- # cluster processes
- My::SafeProcess::shutdown( $opt_shutdown_timeout,
- started(ndbds(), ndb_mgmds()) );
- }
- else
- {
- mtr_report("Restarting ", started(@servers));
+ mtr_report("Restarting ", started(@servers));
- # Stop only some servers
- My::SafeProcess::shutdown( $opt_shutdown_timeout,
- started(@servers) );
- }
+ My::SafeProcess::shutdown($opt_shutdown_timeout,
+ started(@servers));
foreach my $server (@servers)
{
@@ -4823,149 +5278,14 @@ sub stop_servers($$) {
sub start_servers($) {
my ($tinfo)= @_;
- # Make sure the safe_process also exits from now on
- # Could not be done before, as we don't want this for the bootstrap
- if ($opt_start_exit) {
- My::SafeProcess->start_exit();
- }
-
- # Start clusters
- foreach my $cluster ( clusters() )
- {
- ndbcluster_start($cluster);
- }
-
- # Start mysqlds
- foreach my $mysqld ( mysqlds() )
- {
- if ( $mysqld->{proc} )
- {
- # Already started
-
- # Write start of testcase to log file
- mark_log($mysqld->value('#log-error'), $tinfo);
-
- next;
- }
-
- my $datadir= $mysqld->value('datadir');
- if ($opt_start_dirty)
- {
- # Don't delete anything if starting dirty
- ;
- }
- else
- {
-
- my @options= ('log-bin', 'relay-log');
- foreach my $option_name ( @options ) {
- next unless $mysqld->option($option_name);
-
- my $file_name= $mysqld->value($option_name);
- next unless
- defined $file_name and
- -e $file_name;
-
- mtr_debug(" -removing '$file_name'");
- unlink($file_name) or die ("unable to remove file '$file_name'");
- }
-
- if (-d $datadir ) {
- mtr_verbose(" - removing '$datadir'");
- rmtree($datadir);
- }
- }
-
- my $mysqld_basedir= $mysqld->value('basedir');
- if ( $basedir eq $mysqld_basedir )
- {
- if (! $opt_start_dirty) # If dirty, keep possibly grown system db
- {
- # Copy datadir from installed system db
- for my $path ( "$opt_vardir", "$opt_vardir/..") {
- my $install_db= "$path/install.db";
- copytree($install_db, $datadir)
- if -d $install_db;
- }
- mtr_error("Failed to copy system db to '$datadir'")
- unless -d $datadir;
- }
- }
- else
- {
- mysql_install_db($mysqld); # For versional testing
-
- mtr_error("Failed to install system db to '$datadir'")
- unless -d $datadir;
-
- }
-
- # Create the servers tmpdir
- my $tmpdir= $mysqld->value('tmpdir');
- mkpath($tmpdir) unless -d $tmpdir;
-
- # Write start of testcase to log file
- mark_log($mysqld->value('#log-error'), $tinfo);
-
- # Run <tname>-master.sh
- if ($mysqld->option('#!run-master-sh') and
- run_sh_script($tinfo->{master_sh}) )
- {
- $tinfo->{'comment'}= "Failed to execute '$tinfo->{master_sh}'";
- return 1;
- }
-
- # Run <tname>-slave.sh
- if ($mysqld->option('#!run-slave-sh') and
- run_sh_script($tinfo->{slave_sh}))
- {
- $tinfo->{'comment'}= "Failed to execute '$tinfo->{slave_sh}'";
- return 1;
- }
-
- if (!$opt_embedded_server)
- {
- my $extra_opts= get_extra_opts($mysqld, $tinfo);
- mysqld_start($mysqld,$extra_opts);
-
- # Save this test case information, so next can examine it
- $mysqld->{'started_tinfo'}= $tinfo;
- }
-
- }
-
- # Wait for clusters to start
- foreach my $cluster ( clusters() )
- {
- if (ndbcluster_wait_started($cluster, ""))
- {
- # failed to start
- $tinfo->{'comment'}= "Start of '".$cluster->name()."' cluster failed";
- return 1;
- }
+ for (all_servers()) {
+ $_->{START}->($_, $tinfo) if $_->{START};
}
- # Wait for mysqlds to start
- foreach my $mysqld ( mysqlds() )
- {
- next if !started($mysqld);
-
- if (sleep_until_file_created($mysqld->value('pid-file'),
- $opt_start_timeout,
- $mysqld->{'proc'}) == 0) {
- $tinfo->{comment}=
- "Failed to start ".$mysqld->name();
-
- my $logfile= $mysqld->value('#log-error');
- if ( defined $logfile and -f $logfile )
- {
- my @srv_lines= extract_server_log($logfile, $tinfo->{name});
- $tinfo->{logfile}= "Server log is:\n" . join ("", @srv_lines);
- }
- else
- {
- $tinfo->{logfile}= "Could not open server logfile: '$logfile'";
- }
+ for (all_servers()) {
+ next unless $_->{WAIT} and started($_);
+ if ($_->{WAIT}->($_)) {
+ $tinfo->{comment}= "Failed to start ".$_->name();
return 1;
}
}
@@ -5092,6 +5412,10 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "--ssl");
}
+ foreach my $arg ( @opt_extra_mysqltest_opt )
+ {
+ mtr_add_arg($args, "%s", $arg);
+ }
if ( $opt_max_connections ) {
mtr_add_arg($args, "--max-connections=%d", $opt_max_connections);
}
@@ -5115,10 +5439,17 @@ sub start_mysqltest ($) {
if (IS_WINDOWS)
{
# Trick the server to send output to stderr, with --console
- mtr_add_arg($args, "--server-arg=--console");
+ if (!(grep(/^--server-arg=--log-error/, @$args))) {
+ mtr_add_arg($args, "--server-arg=--console");
+ }
}
}
+ foreach my $arg ( @opt_extra_mysqltest_opt )
+ {
+ mtr_add_arg($args, "%s", $arg);
+ }
+
# ----------------------------------------------------------------------
# export MYSQL_TEST variable containing <path>/mysqltest <args>
# ----------------------------------------------------------------------
@@ -5205,20 +5536,12 @@ sub gdb_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\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");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
if ( $opt_manual_gdb )
@@ -5269,20 +5592,12 @@ sub ddd_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\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");
+ mtr_tofile($gdb_init_file, "file $$exe\nset args $str\n");
}
if ( $opt_manual_ddd )
@@ -5400,66 +5715,33 @@ sub valgrind_arguments {
}
#
-# Search server logs for valgrind reports printed at mysqld termination
+# Modify the exe and args so that program is run in strace
#
+sub strace_arguments {
+ my $args= shift;
+ my $exe= shift;
+ my $mysqld_name= shift;
-sub valgrind_exit_reports() {
- foreach my $log_file (keys %mysqld_logs)
- {
- my @culprits= ();
- my $valgrind_rep= "";
- my $found_report= 0;
- my $err_in_report= 0;
+ mtr_add_arg($args, "-f");
+ mtr_add_arg($args, "-o%s/var/log/%s.strace", $glob_mysql_test_dir, $mysqld_name);
- my $LOGF = IO::File->new($log_file)
- or mtr_error("Could not open file '$log_file' for reading: $!");
+ # Add strace options, can be overriden by user
+ mtr_add_arg($args, '%s', $_) for (@strace_args);
- while ( my $line = <$LOGF> )
- {
- if ($line =~ /^CURRENT_TEST: (.+)$/)
- {
- my $testname= $1;
- # If we have a report, report it if needed and start new list of tests
- if ($found_report)
- {
- if ($err_in_report)
- {
- mtr_print ("Valgrind report from $log_file after tests:\n",
- @culprits);
- mtr_print_line();
- print ("$valgrind_rep\n");
- $err_in_report= 0;
- }
- # Make ready to collect new report
- @culprits= ();
- $found_report= 0;
- $valgrind_rep= "";
- }
- push (@culprits, $testname);
- next;
- }
- # This line marks the start of a valgrind report
- $found_report= 1 if $line =~ /ERROR SUMMARY:/;
-
- if ($found_report) {
- $line=~ s/^==\d+== //;
- $valgrind_rep .= $line;
- $err_in_report= 1 if $line =~ /ERROR SUMMARY: [1-9]/;
- $err_in_report= 1 if $line =~ /definitely lost: [1-9]/;
- $err_in_report= 1 if $line =~ /possibly lost: [1-9]/;
- }
- }
+ mtr_add_arg($args, $$exe);
- $LOGF= undef;
+ $$exe= "strace";
- if ($err_in_report) {
- mtr_print ("Valgrind report from $log_file after tests:\n", @culprits);
- mtr_print_line();
- print ("$valgrind_rep\n");
- }
+ if ($exe_libtool)
+ {
+ # Add "libtool --mode-execute" before the test to execute
+ # if running in valgrind(to avoid valgrinding bash)
+ unshift(@$args, "--mode=execute", $$exe);
+ $$exe= $exe_libtool;
}
}
+
#
# Usage
#
@@ -5469,6 +5751,8 @@ sub usage ($) {
if ( $message )
{
print STDERR "$message\n";
+ print STDERR "For full list of options, use $0 --help\n";
+ exit;
}
print <<HERE;
@@ -5488,12 +5772,12 @@ Options to control what engine/variation to run
skip-ssl Dont start server with support for ssl connections
vs-config Visual Studio configuration used to create executables
(default: MTR_VS_CONFIG environment variable)
-
+ parallel=# How many parallell test should be run
defaults-file=<config template> Use fixed config template for all
tests
defaults_extra_file=<config template> Extra config template to add to
all generated configs
- combination=<opt> Use at least twice to run tests with specified
+ combination=<opt> Use at least twice to run tests with specified
options to mysqld
skip-combinations Ignore combination file (or options)
@@ -5533,6 +5817,8 @@ Options to control what test suites or cases to run
The default is: "$DEFAULT_SUITES"
skip-rpl Skip the replication test cases.
big-test Also run tests marked as "big"
+ staging-run Run a limited number of tests (no slow tests). Used
+ for running staging trees with valgrind.
enable-disabled Run also tests marked as disabled
print-testcases Don't run the tests but print details about all the
selected tests, in the order they would be run.
@@ -5561,6 +5847,7 @@ Options for test case authoring
Options that pass on options
mysqld=ARGS Specify additional arguments to "mysqld"
+ mysqltest=ARGS Specify additional arguments to "mysqltest"
Options to run test on running server
@@ -5585,9 +5872,6 @@ Options for debugging the product
test(s)
manual-ddd Let user manually start mysqld in ddd, before running
test(s)
- strace-client=[path] Create strace output for mysqltest client, optionally
- specifying name and path to the trace program to use.
- Example: $0 --strace-client=ktrace
max-save-core Limit the number of core files saved (to avoid filling
up disks for heavily crashing server). Defaults to
$opt_max_save_core, set to 0 for no limit. Set
@@ -5615,6 +5899,15 @@ Options for valgrind
valgrind-path=<EXE> Path to the valgrind executable
callgrind Instruct valgrind to use callgrind
+Options for strace
+
+ strace Run the "mysqld" executables using strace. Default
+ options are -f -o var/log/'mysqld-name'.strace
+ strace-option=ARGS Option to give strace, replaces default option(s),
+ strace-client=[path] Create strace output for mysqltest client, optionally
+ specifying name and path to the trace program to use.
+ Example: $0 --strace-client=ktrace
+
Misc options
user=USER User for connecting to mysqld(default: $opt_user)
comment=STR Write STR to the output
@@ -5637,12 +5930,15 @@ Misc options
fast Run as fast as possible, dont't wait for servers
to shutdown etc.
force-restart Always restart servers between tests
- parallel=N Run tests in N parallel threads (default=1)
+ parallel=N Run tests in N parallel threads (default 1)
Use parallel=auto for auto-setting of N
repeat=N Run each test N number of times
- retry=N Retry tests that fail N times, limit number of failures
- to $opt_retry_failure
- retry-failure=N Limit number of retries for a failed test
+ retry=N Retry tests that fail up to N times (default $opt_retry).
+ Retries are also limited by the maximum number of
+ failures before stopping, set with the --retry-failure
+ option
+ retry-failure=N When using the --retry option to retry failed tests,
+ stop when N failures have occured (default $opt_retry_failure)
reorder Reorder tests to get fewer server restarts
help Get this help text
@@ -5653,11 +5949,22 @@ Misc options
warnings Scan the log files for warnings. Use --nowarnings
to turn off.
+ stop-file=file (also MTR_STOP_FILE environment variable) if this
+ file detected mysql test will not start new tests
+ until the file will be removed.
+ stop-keep-alive=sec (also MTR_STOP_KEEP_ALIVE environment variable)
+ works with stop-file, print messages every sec
+ seconds when mysql test is waiting to removing
+ the file (for buildbot)
+
sleep=SECONDS Passed to mysqltest, will be used as fixed sleep time
debug-sync-timeout=NUM Set default timeout for WAIT_FOR debug sync
actions. Disable facility with NUM=0.
gcov Collect coverage information after the test.
The result is a gcov file per source and header file.
+ gcov-src-dir=subdir Colllect coverage only within the given subdirectory.
+ For example, if you're only developing the SQL layer,
+ it makes sense to use --gcov-src-dir=sql
experimental=<file> Refer to list of tests considered experimental;
failures will be marked exp-fail instead of fail.
report-features First run a "test" that reports mysql features
@@ -5679,9 +5986,30 @@ sub list_options ($) {
for (keys %$hash) {
s/([:=].*|[+!])$//;
s/\|/\n--/g;
- print "--$_\n" unless /list-options/;
+ print "--$_\n";
}
exit(1);
}
+sub time_format($) {
+ sprintf '%d:%02d:%02d', $_[0]/3600, ($_[0]/60)%60, $_[0]%60;
+}
+
+my $num_tests;
+
+sub xterm_stat {
+ if (-t STDOUT and defined $ENV{TERM} and $ENV{TERM} =~ /xterm/) {
+ my ($left) = @_;
+
+ # 2.5 -> best by test
+ $num_tests = $left + 2.5 unless $num_tests;
+
+ my $done = $num_tests - $left;
+ my $spent = time - $^T;
+
+ printf "\e];mtr: spent %s on %d tests. %s (%d tests) left\a",
+ time_format($spent), $done,
+ time_format($spent/$done * $left), $left;
+ }
+}