diff options
Diffstat (limited to 'mysql-test/lib')
-rw-r--r-- | mysql-test/lib/My/Config.pm | 131 | ||||
-rw-r--r-- | mysql-test/lib/My/ConfigFactory.pm | 68 | ||||
-rw-r--r-- | mysql-test/lib/My/File/Path.pm | 2 | ||||
-rw-r--r-- | mysql-test/lib/My/SafeProcess.pm | 16 | ||||
-rw-r--r-- | mysql-test/lib/My/SafeProcess/safe_process.cc | 47 | ||||
-rw-r--r-- | mysql-test/lib/My/Suite.pm | 10 | ||||
-rw-r--r-- | mysql-test/lib/My/Test.pm | 81 | ||||
-rw-r--r-- | mysql-test/lib/mtr_cases.pm | 392 | ||||
-rw-r--r-- | mysql-test/lib/mtr_gcov.pl | 6 | ||||
-rw-r--r-- | mysql-test/lib/mtr_misc.pl | 20 | ||||
-rw-r--r-- | mysql-test/lib/mtr_report.pm | 38 | ||||
-rwxr-xr-x | mysql-test/lib/process-purecov-annotations.pl | 63 | ||||
-rw-r--r-- | mysql-test/lib/v1/mtr_process.pl | 40 | ||||
-rw-r--r-- | mysql-test/lib/v1/mtr_report.pl | 25 | ||||
-rwxr-xr-x | mysql-test/lib/v1/mysql-test-run.pl | 171 |
15 files changed, 627 insertions, 483 deletions
diff --git a/mysql-test/lib/My/Config.pm b/mysql-test/lib/My/Config.pm index 315e415e219..bf6629754a1 100644 --- a/mysql-test/lib/My/Config.pm +++ b/mysql-test/lib/My/Config.pm @@ -6,7 +6,6 @@ use strict; use warnings; use Carp; - sub new { my ($class, $option_name, $option_value)= @_; my $self= bless { name => $option_name, @@ -61,7 +60,7 @@ sub insert { $option->{value}= $value; } else { - my $option= My::Config::Option->new($option_name, $value); + $option= My::Config::Option->new($option_name, $value); # Insert option in list push(@{$self->{options}}, $option); # Insert option in hash @@ -163,6 +162,62 @@ sub if_exist { return $option->value(); } +package My::Config::Group::ENV; +our @ISA=qw(My::Config::Group); + +use strict; +use warnings; +use Carp; + +sub new { + my ($class, $group_name)= @_; + bless My::Config::Group->new($group_name), $class; +} + +# +# Return value for an option in the group, fail if it does not exist +# +sub value { + my ($self, $option_name)= @_; + my $option= $self->option($option_name); + + if (! defined($option) and defined $ENV{$option_name}) { + my $value= $ENV{$option_name}; + $option= My::Config::Option->new($option_name, $value); + } + + croak "No option named '$option_name' in group '$self->{name}'" + if ! defined($option); + + return $option->value(); +} + +package My::Config::Group::OPT; +our @ISA=qw(My::Config::Group); + +use strict; +use warnings; +use Carp; + +sub new { + my ($class, $group_name)= @_; + bless My::Config::Group->new($group_name), $class; +} + +sub options { + my ($self)= @_; + () +} + +sub value { + my ($self, $option_name)= @_; + my $option= $self->option($option_name); + + croak "No option named '$option_name' in group '$self->{name}'" + if ! defined($option); + + return $option->value()->(); +} package My::Config; @@ -182,7 +237,10 @@ sub new { my ($class, $path)= @_; my $group_name= undef; - my $self= bless { groups => [] }, $class; + my $self= bless { groups => [ + My::Config::Group::ENV->new('ENV'), + My::Config::Group::OPT->new('OPT'), + ] }, $class; my $F= IO::File->new($path, "<") or croak "Could not open '$path': $!"; @@ -201,19 +259,13 @@ sub new { } # Magic #! comments - elsif ( $line =~ /^#\!/) { - my $magic= $line; + elsif ( $line =~ /^(#\!\S+)(?:\s*(.*?)\s*)?$/) { + my ($magic, $arg)= ($1, $2); croak "Found magic comment '$magic' outside of group" unless $group_name; #print "$magic\n"; - $self->insert($group_name, $magic, undef); - } - - # Comments - elsif ( $line =~ /^#/ || $line =~ /^;/) { - # Skip comment - next; + $self->insert($group_name, $magic, $arg); } # Empty lines @@ -238,7 +290,7 @@ sub new { } # <option> - elsif ( $line =~ /^([\@\w-]+)\s*$/ ) { + elsif ( $line =~ /^(#?[\w-]+)\s*$/ ) { my $option= $1; croak "Found option '$option' outside of group" @@ -249,7 +301,7 @@ sub new { } # <option>=<value> - elsif ( $line =~ /^([\@\w-]+)\s*=\s*(.*?)\s*$/ ) { + elsif ( $line =~ /^(#?[\w-]+)\s*=\s*(.*?)\s*$/ ) { my $option= $1; my $value= $2; @@ -258,10 +310,17 @@ sub new { #print "$option=$value\n"; $self->insert($group_name, $option, $value); - } else { - croak "Unexpected line '$line' found in '$path'"; } + # Comments + elsif ( $line =~ /^#/ || $line =~ /^;/) { + # Skip comment + next; + } + + else { + croak "Unexpected line '$line' found in '$path'"; + } } undef $F; # Close the file @@ -439,44 +498,4 @@ sub exists { return defined($option); } - -# Overload "to string"-operator with 'stringify' -use overload - '""' => \&stringify; - -# -# Return the config as a string in my.cnf file format -# -sub stringify { - my ($self)= @_; - my $res; - - foreach my $group ($self->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"; - } - return $res; -} - - -# -# Save the config to named file -# -sub save { - my ($self, $path)= @_; - my $F= IO::File->new($path, ">") - or croak "Could not open '$path': $!"; - print $F $self; - undef $F; # Close the file -} - 1; diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index 19c3ee4d5d8..8fb0e27eb77 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -20,7 +20,7 @@ my @pre_rules= ); -my @share_locations= ("share/mysql", "sql/share", "share"); +my @share_locations= ("share/mariadb", "share/mysql", "sql/share", "share"); sub get_basedir { @@ -73,16 +73,12 @@ sub fix_pidfile { sub fix_port { my ($self, $config, $group_name, $group)= @_; - my $hostname= $group->value('#host'); - return $self->{HOSTS}->{$hostname}++; + return $self->{PORT}++; } sub fix_host { my ($self)= @_; - # Get next host from HOSTS array - my @hosts= keys(%{$self->{HOSTS}});; - my $host_no= $self->{NEXT_HOST}++ % @hosts; - return $hosts[$host_no]; + 'localhost' } sub is_unique { @@ -158,6 +154,7 @@ sub fix_secure_file_priv { sub fix_std_data { my ($self, $config, $group_name, $group)= @_; + #return "$::opt_vardir/std_data"; my $testdir= $self->get_testdir($group); return "$testdir/std_data"; } @@ -219,12 +216,13 @@ my @mysqld_rules= { 'pid-file' => \&fix_pidfile }, { '#host' => \&fix_host }, { 'port' => \&fix_port }, + { '#extra-port' => \&fix_port }, { 'socket' => \&fix_socket }, { '#log-error' => \&fix_log_error }, - { 'general_log' => 1 }, - { 'general_log_file' => \&fix_log }, - { 'slow_query_log' => 1 }, - { 'slow_query_log_file' => \&fix_log_slow_queries }, + { 'general-log' => sub { return 1; } }, + { 'general-log-file' => \&fix_log }, + { 'slow-query-log' => sub { return 1; } }, + { 'slow-query-log-file' => \&fix_log_slow_queries }, { '#user' => sub { return shift->{ARGS}->{user} || ""; } }, { '#password' => sub { return shift->{ARGS}->{password} || ""; } }, { 'server-id' => \&fix_server_id, }, @@ -245,7 +243,7 @@ if (IS_WINDOWS) sub fix_ndb_mgmd_port { my ($self, $config, $group_name, $group)= @_; my $hostname= $group->value('HostName'); - return $self->{HOSTS}->{$hostname}++; + return $self->{PORT}++; } @@ -389,7 +387,7 @@ sub post_check_client_group { sub post_check_client_groups { my ($self, $config)= @_; - my $first_mysqld= $config->first_like('mysqld.'); + my $first_mysqld= $config->first_like('mysqld\.'); return unless $first_mysqld; @@ -444,20 +442,24 @@ sub post_check_embedded_group { sub resolve_at_variable { my ($self, $config, $group, $option)= @_; + local $_ = $option->value(); + my ($res, $after); - # Split the options value on last . - my @parts= split(/\./, $option->value()); - my $option_name= pop(@parts); - my $group_name= join('.', @parts); + while (m/(.*?)\@((?:\w+\.)+)(#?[-\w]+)/g) { + my ($before, $group_name, $option_name)= ($1, $2, $3); + $after = $'; + chop($group_name); - $group_name =~ s/^\@//; # Remove at + my $from_group= $config->group($group_name) + or croak "There is no group named '$group_name' that ", + "can be used to resolve '$option_name'"; - my $from_group= $config->group($group_name) - or croak "There is no group named '$group_name' that ", - "can be used to resolve '$option_name'"; + my $value= $from_group->value($option_name); + $res .= $before.$value; + } + $res .= $after; - my $from= $from_group->value($option_name); - $config->insert($group->name(), $option->name(), $from) + $config->insert($group->name(), $option->name(), $res) } @@ -469,7 +471,7 @@ sub post_fix_resolve_at_variables { next unless defined $option->value(); $self->resolve_at_variable($config, $group, $option) - if ($option->value() =~ /^\@/); + if ($option->value() =~ /\@/); } } } @@ -611,28 +613,18 @@ sub new_config { croak "you must pass '$required'" unless defined $args->{$required}; } - # Fill in hosts/port hash - my $hosts= {}; - my $baseport= $args->{baseport}; - $args->{hosts}= [ 'localhost' ] unless exists($args->{hosts}); - foreach my $host ( @{$args->{hosts}} ) { - $hosts->{$host}= $baseport; - } - # Open the config template my $config= My::Config->new($args->{'template_path'}); - my $extra_template_path= $args->{'extra_template_path'}; - if ($extra_template_path){ - $config->append(My::Config->new($extra_template_path)); - } my $self= bless { CONFIG => $config, ARGS => $args, - HOSTS => $hosts, - NEXT_HOST => 0, + PORT => $args->{baseport}, SERVER_ID => 1, }, $class; + # add auto-options + $config->insert('OPT', 'port' => sub { fix_port($self, $config) }); + $config->insert('OPT', 'vardir' => sub { $self->{ARGS}->{vardir} }); { # Run pre rules diff --git a/mysql-test/lib/My/File/Path.pm b/mysql-test/lib/My/File/Path.pm index 25a26568eee..6e6d23ad9f0 100644 --- a/mysql-test/lib/My/File/Path.pm +++ b/mysql-test/lib/My/File/Path.pm @@ -18,7 +18,7 @@ use strict; use Exporter; use base "Exporter"; -our @EXPORT= qw / rmtree mkpath copytree /; +our @EXPORT= qw /rmtree mkpath copytree/; use File::Find; use File::Copy; diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index 461897b56f0..59186f50703 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -133,7 +133,7 @@ sub new { my $input = delete($opts{'input'}); my $output = delete($opts{'output'}); my $error = delete($opts{'error'}); - my $verbose = delete($opts{'verbose'}); + my $verbose = delete($opts{'verbose'}) || $::opt_verbose; my $nocore = delete($opts{'nocore'}); my $host = delete($opts{'host'}); my $shutdown = delete($opts{'shutdown'}); @@ -349,9 +349,9 @@ sub kill { sub _collect { - my ($self)= @_; + my ($self, $exit_code)= @_; - $self->{EXIT_STATUS}= $?; + $self->{EXIT_STATUS}= $exit_code; _verbose("_collect: $self"); # Take the process out of running list @@ -418,6 +418,7 @@ sub wait_one { #_verbose("blocking: $blocking, use_alarm: $use_alarm"); my $retpid; + my $exit_code; eval { # alarm should break the wait @@ -426,6 +427,7 @@ sub wait_one { alarm($timeout) if $use_alarm; $retpid= waitpid($pid, $blocking ? 0 : &WNOHANG); + $exit_code= $?; alarm(0) if $use_alarm; }; @@ -457,7 +459,7 @@ sub wait_one { #warn "wait_one: expected pid $pid but got $retpid" # unless( $retpid == $pid ); - $self->_collect(); + $self->_collect($exit_code); return 0; } @@ -470,6 +472,8 @@ sub wait_one { # sub wait_any { my $ret_pid; + my $exit_code; + if (IS_WIN32PERL) { # Can't wait for -1 => use a polling loop do { @@ -479,6 +483,7 @@ sub wait_any { last if $pid == $ret_pid; } } while ($ret_pid == 0); + $exit_code= $?; } else { @@ -488,6 +493,7 @@ sub wait_any { print STDERR "wait_any, got invalid pid: $ret_pid\n"; return undef; } + $exit_code= $?; } # Look it up in "running" table @@ -497,7 +503,7 @@ sub wait_any { print STDERR "running: ". join(", ", keys(%running)). "\n"; return undef; } - $proc->_collect; + $proc->_collect($exit_code); return $proc; } diff --git a/mysql-test/lib/My/SafeProcess/safe_process.cc b/mysql-test/lib/My/SafeProcess/safe_process.cc index 1c778362975..12b335ec444 100644 --- a/mysql-test/lib/My/SafeProcess/safe_process.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process.cc @@ -85,17 +85,18 @@ static void die(const char* fmt, ...) va_end(args); if (int last_err= errno) fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err)); - exit(1); + exit(6); } -static void kill_child(void) +static void kill_child(bool was_killed) { int status= 0; message("Killing child: %d", child_pid); // Terminate whole process group - kill(-child_pid, SIGKILL); + if (! was_killed) + kill(-child_pid, SIGKILL); pid_t ret_pid= waitpid(child_pid, &status, 0); if (ret_pid == child_pid) @@ -115,7 +116,7 @@ static void kill_child(void) exit(exit_code); } - exit(1); + exit(5); } @@ -135,7 +136,7 @@ extern "C" void handle_signal(int sig) terminated= 1; if (child_pid > 0) - kill_child(); + kill_child(sig == SIGCHLD); // Ignore further signals signal(SIGTERM, SIG_IGN); @@ -240,8 +241,8 @@ int main(int argc, char* const argv[] ) // Close write end close(pfd[1]); - if (execvp(child_argv[0], child_argv) < 0) - die("Failed to exec child"); + execvp(child_argv[0], child_argv); + die("Failed to exec child"); } close(pfd[1]); // Close unused write end @@ -257,39 +258,19 @@ int main(int argc, char* const argv[] ) /* Monitor loop */ message("Started child %d, terminated: %d", child_pid, terminated); - while(!terminated) + while (!terminated) { // Check if parent is still alive - if (kill(parent_pid, 0) != 0){ + if (kill(parent_pid, 0) != 0) + { message("Parent is not alive anymore"); break; } - - // Check if child has exited, normally this will be - // detected immediately with SIGCHLD handler - int status= 0; - pid_t ret_pid= waitpid(child_pid, &status, WNOHANG); - if (ret_pid == child_pid) - { - int ret_code= 2; - if (WIFEXITED(status)) - { - // Process has exited, collect return status - ret_code= WEXITSTATUS(status); - message("Child exit: %d", ret_code); - // Exit with exit status of the child - exit(ret_code); - } - - if (WIFSIGNALED(status)) - message("Child killed by signal: %d", WTERMSIG(status)); - - exit(ret_code); - } + /* Wait for parent or child to die */ sleep(1); } - kill_child(); + kill_child(0); - return 1; + return 4; } diff --git a/mysql-test/lib/My/Suite.pm b/mysql-test/lib/My/Suite.pm new file mode 100644 index 00000000000..69609e1c4f5 --- /dev/null +++ b/mysql-test/lib/My/Suite.pm @@ -0,0 +1,10 @@ +# A default suite class that is used for all suites without their owns suite.pm +# see README.suites for a description + +package My::Suite; + +sub config_files { () } +sub servers { () } + +bless { }; + diff --git a/mysql-test/lib/My/Test.pm b/mysql-test/lib/My/Test.pm index 68b100f91af..c8bfbd34521 100644 --- a/mysql-test/lib/My/Test.pm +++ b/mysql-test/lib/My/Test.pm @@ -9,6 +9,7 @@ package My::Test; use strict; use warnings; use Carp; +use Storable(); sub new { @@ -19,6 +20,12 @@ sub new { return $self; } +sub fullname { + my ($self)= @_; + $self->{name} . (defined $self->{combination} + ? " '$self->{combination}'" + : "") +} # # Return a unique key that can be used to @@ -30,18 +37,6 @@ sub key { } -sub _encode { - my ($value)= @_; - $value =~ s/([|\\\x{0a}\x{0d}])/sprintf('\%02X', ord($1))/eg; - return $value; -} - -sub _decode { - my ($value)= @_; - $value =~ s/\\([0-9a-fA-F]{2})/chr(hex($1))/ge; - return $value; -} - sub is_failed { my ($self)= @_; my $result= $self->{result}; @@ -58,66 +53,22 @@ sub write_test { # Give the test a unique key before serializing it $test->{key}= "$test" unless defined $test->{key}; - print $sock $header, "\n"; - while ((my ($key, $value)) = each(%$test)) { - print $sock $key, "= "; - if (ref $value eq "ARRAY") { - print $sock "[", _encode(join(", ", @$value)), "]"; - } else { - print $sock _encode($value); - } - print $sock "\n"; - } - print $sock "\n"; + my $serialized= Storable::freeze($test); + $serialized =~ s/([\x0d\x0a\\])/sprintf("\\%02x", ord($1))/eg; + print $sock $header, "\n", $serialized, "\n"; } sub read_test { my ($sock)= @_; - my $test= My::Test->new(); - # Read the : separated key value pairs until a - # single newline on it's own line - my $line; - while (defined($line= <$sock>)) { - # List is terminated by newline on it's own - if ($line eq "\n") { - # Correctly terminated reply - # print "Got newline\n"; - last; - } - chomp($line); - - # Split key/value on the first "=" - my ($key, $value)= split("= ", $line, 2); - - if ($value =~ /^\[(.*)\]/){ - my @values= split(", ", _decode($1)); - push(@{$test->{$key}}, @values); - } - else - { - $test->{$key}= _decode($value); - } - } + my $serialized= <$sock>; + chomp($serialized); + $serialized =~ s/\\([0-9a-fA-F]{2})/chr(hex($1))/eg; + my $test= Storable::thaw($serialized); + die "wrong class (hack attempt?)" + unless ref($test) eq 'My::Test'; return $test; } -sub print_test { - my ($self)= @_; - - print "[", $self->{name}, "]", "\n"; - while ((my ($key, $value)) = each(%$self)) { - print " ", $key, "= "; - if (ref $value eq "ARRAY") { - print "[", join(", ", @$value), "]"; - } else { - print $value; - } - print "\n"; - } - print "\n"; -} - - 1; diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 87f96496c73..ebdc8fa9f98 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -39,14 +39,7 @@ our $enable_disabled; our $default_storage_engine; our $opt_with_ndbcluster_only; our $defaults_file; -our $defaults_extra_file; our $quick_collect; -# Set to 1 if you want the tests to override -# default storage engine settings, and use MyISAM -# as default. (temporary option used in connection -# with the change of default storage engine to InnoDB) -our $default_myisam= 1; - sub collect_option { my ($opt, $value)= @_; @@ -61,7 +54,7 @@ sub collect_option { } use File::Basename; -use File::Spec::Functions qw / splitdir /; +use File::Spec::Functions qw /splitdir/; use IO::File(); use My::Config; use My::Platform; @@ -74,13 +67,11 @@ require "mtr_misc.pl"; my $do_test_reg; my $skip_test_reg; -# Related to adding InnoDB plugin combinations -my $lib_innodb_plugin; -my $do_innodb_plugin; - # If "Quick collect", set to 1 once a test to run has been found. my $some_test_found; +my $default_suite_object = do 'My/Suite.pm'; + sub init_pattern { my ($from, $what)= @_; return undef unless defined $from; @@ -114,17 +105,6 @@ sub collect_test_cases ($$$$) { $do_test_reg= init_pattern($do_test, "--do-test"); $skip_test_reg= init_pattern($skip_test, "--skip-test"); - $lib_innodb_plugin= - my_find_file($::basedir, - ["storage/innodb_plugin", "storage/innodb_plugin/.libs", - "lib/mysql/plugin", "lib/plugin"], - ["ha_innodb_plugin.dll", "ha_innodb_plugin.so", - "ha_innodb_plugin.sl"], - NOT_REQUIRED); - $do_innodb_plugin= ($::mysql_version_id >= 50100 && - !(IS_WINDOWS && $::opt_embedded_server) && - $lib_innodb_plugin); - # If not reordering, we also shouldn't group by suites, unless # no test cases were named. # This also effects some logic in the loop following this. @@ -195,17 +175,17 @@ sub collect_test_cases ($$$$) { my $opts= $tinfo->{'master_opt'} ? $tinfo->{'master_opt'} : []; push(@criteria, join("!", sort @{$opts}) . "~"); - $sort_criteria{$tinfo->{name}} = join(" ", @criteria); + $sort_criteria{$tinfo->fullname()} = join(" ", @criteria); } @$cases = sort { - $sort_criteria{$a->{'name'}} . $a->{'name'} cmp - $sort_criteria{$b->{'name'}} . $b->{'name'}; } @$cases; + $sort_criteria{$a->fullname()} . $a->fullname() cmp + $sort_criteria{$b->fullname()} . $b->fullname() } @$cases; # For debugging the sort-order # foreach my $tinfo (@$cases) # { - # print("$sort_criteria{$tinfo->{'name'}} -> \t$tinfo->{'name'}\n"); + # print $sort_criteria{$tinfo->fullname()}," -> \t",$tinfo->fullname(),"\n"; # } } @@ -253,7 +233,7 @@ sub split_testname { } -sub collect_one_suite($) +sub collect_one_suite { my $suite= shift; # Test suite name my $opt_cases= shift; @@ -315,6 +295,17 @@ sub collect_one_suite($) mtr_verbose("testdir: $testdir"); mtr_verbose("resdir: $resdir"); + # + # Load the Suite object + # + unless ($::suites{$suite}) { + if (-f "$suitedir/suite.pm") { + $::suites{$suite} = do "$suitedir/suite.pm"; + } else { + $::suites{$suite} = $default_suite_object; + } + } + # ---------------------------------------------------------------------- # Build a hash of disabled testcases for this suite # ---------------------------------------------------------------------- @@ -338,12 +329,8 @@ sub collect_one_suite($) } # Read suite.opt file - my $suite_opt_file= "$testdir/suite.opt"; - my $suite_opts= []; - if ( -f $suite_opt_file ) - { - $suite_opts= opts_from_file($suite_opt_file); - } + my $suite_opts= [ opts_from_file("$testdir/suite.opt") ]; + $suite_opts = [ opts_from_file("$suitedir/suite.opt") ] unless @$suite_opts; if ( @$opt_cases ) { @@ -448,14 +435,16 @@ sub collect_one_suite($) { # Read combinations file in my.cnf format mtr_verbose("Read combinations file"); + my %env_filter = map { $_ => 1 } split /:/, $ENV{"\U${suite}_COMBINATIONS"}; my $config= My::Config->new($combination_file); foreach my $group ($config->groups()) { my $comb= {}; $comb->{name}= $group->name(); + next if %env_filter and not $env_filter{$comb->{name}}; foreach my $option ( $group->options() ) { push(@{$comb->{comb_opt}}, $option->option()); } - push(@combinations, $comb); + push(@combinations, $comb) if $comb->{comb_opt}; } } @@ -534,8 +523,12 @@ sub collect_one_suite($) sub optimize_cases { my ($cases)= @_; + my @new_cases= (); + foreach my $tinfo ( @$cases ) { + push @new_cases, $tinfo; + # Skip processing if already marked as skipped next if $tinfo->{skip}; @@ -545,28 +538,7 @@ sub optimize_cases { # support it # ======================================================= #print "binlog_format: $binlog_format\n"; - if (defined $binlog_format ) - { - # ======================================================= - # Fixed --binlog-format=x specified on command line - # ======================================================= - if ( defined $tinfo->{'binlog_formats'} ) - { - #print "binlog_formats: ". join(", ", @{$tinfo->{binlog_formats}})."\n"; - - # The test supports different binlog formats - # check if the selected one is ok - my $supported= - grep { $_ eq $binlog_format } @{$tinfo->{'binlog_formats'}}; - if ( !$supported ) - { - $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= - "Doesn't support --binlog-format='$binlog_format'"; - } - } - } - else + if (not defined $binlog_format ) { # ======================================================= # Use dynamic switching of binlog format @@ -589,6 +561,13 @@ sub optimize_cases { $tinfo->{'skip'}= 1; $tinfo->{'comment'}= "Doesn't support --binlog-format='$test_binlog_format'"; + # This test was added as a replication combination, but it is not + # actually ever possible to run it, as it is not made for this + # combination. + # So delete it from the list, rather than confuse the user with a + # message that this test is skipped (it is not really, just run + # with other combinations). + pop(@new_cases); next; } } @@ -625,8 +604,6 @@ sub optimize_cases { $tinfo->{'ndb_test'}= 1 if ( $default_engine =~ /^ndb/i ); - $tinfo->{'innodb_test'}= 1 - if ( $default_engine =~ /^innodb/i ); } } @@ -636,6 +613,7 @@ sub optimize_cases { return; } } + @$cases= @new_cases; } @@ -643,74 +621,88 @@ sub optimize_cases { # Read options from the given opt file and append them as an array # to $tinfo->{$opt_name} # -sub process_opts_file { - my ($tinfo, $opt_file, $opt_name)= @_; +sub process_opts { + my ($tinfo, $opt_name)= @_; + + my @opts= @{$tinfo->{$opt_name}}; + $tinfo->{$opt_name} = []; + + my @plugins; + my %seen; - if ( -f $opt_file ) + foreach my $opt (@opts) { - my $opts= opts_from_file($opt_file); + my $value; - foreach my $opt ( @$opts ) + # The opt file is used both to send special options to the mysqld + # as well as pass special test case specific options to this + # script + + $value= mtr_match_prefix($opt, "--timezone="); + if ( defined $value ) { - my $value; + $tinfo->{'timezone'}= $value; + next; + } - # The opt file is used both to send special options to the mysqld - # as well as pass special test case specific options to this - # script + $value= mtr_match_prefix($opt, "--plugin-load="); + if (defined $value) + { + push @plugins, $value unless $seen{$value}; + $seen{$value}=1; + next; + } - $value= mtr_match_prefix($opt, "--timezone="); - if ( defined $value ) - { - $tinfo->{'timezone'}= $value; - next; - } + $value= mtr_match_prefix($opt, "--result-file="); + if ( defined $value ) + { + # Specifies the file mysqltest should compare + # output against + $tinfo->{'result_file'}= "r/$value.result"; + next; + } - $value= mtr_match_prefix($opt, "--result-file="); - if ( defined $value ) - { - # Specifies the file mysqltest should compare - # output against - $tinfo->{'result_file'}= "r/$value.result"; - next; - } + $value= mtr_match_prefix($opt, "--config-file-template="); + if ( defined $value) + { + # Specifies the configuration file to use for this test + $tinfo->{'template_path'}= dirname($tinfo->{path})."/$value"; + next; + } - $value= mtr_match_prefix($opt, "--config-file-template="); - if ( defined $value) - { - # Specifies the configuration file to use for this test - $tinfo->{'template_path'}= dirname($tinfo->{path})."/$value"; - next; - } + # If we set default time zone, remove the one we have + $value= mtr_match_prefix($opt, "--default-time-zone="); + if ( defined $value ) + { + # Set timezone for this test case to something different + $tinfo->{'timezone'}= "GMT-8"; + # Fallthrough, add the --default-time-zone option + } - # If we set default time zone, remove the one we have - $value= mtr_match_prefix($opt, "--default-time-zone="); - if ( defined $value ) - { - # Set timezone for this test case to something different - $tinfo->{'timezone'}= "GMT-8"; - # Fallthrough, add the --default-time-zone option - } + # The --restart option forces a restart even if no special + # option is set. If the options are the same as next testcase + # there is no need to restart after the testcase + # has completed + if ( $opt eq "--force-restart" ) + { + $tinfo->{'force_restart'}= 1; + next; + } - # The --restart option forces a restart even if no special - # option is set. If the options are the same as next testcase - # there is no need to restart after the testcase - # has completed - if ( $opt eq "--force-restart" ) - { - $tinfo->{'force_restart'}= 1; - next; - } + $value= mtr_match_prefix($opt, "--testcase-timeout="); + if ( defined $value ) { + # Overrides test case timeout for this test + $tinfo->{'case-timeout'}= $value; + next; + } - $value= mtr_match_prefix($opt, "--testcase-timeout="); - if ( defined $value ) { - # Overrides test case timeout for this test - $tinfo->{'case-timeout'}= $value; - next; - } + # Ok, this was a real option, add it + push(@{$tinfo->{$opt_name}}, $opt); + } - # Ok, this was a real option, add it - push(@{$tinfo->{$opt_name}}, $opt); - } + if (@plugins) { + my $sep = (IS_WINDOWS) ? ';' : ':'; + push @{$tinfo->{$opt_name}}, "--plugin-load=" . join($sep, @plugins); } } @@ -730,6 +722,8 @@ sub collect_one_test_case { my $disabled= shift; my $suite_opts= shift; + my $local_default_storage_engine= $default_storage_engine; + #print "collect_one_test_case\n"; #print " suitedir: $suitedir\n"; #print " testdir: $testdir\n"; @@ -741,7 +735,7 @@ sub collect_one_test_case { # ---------------------------------------------------------------------- # Check --start-from # ---------------------------------------------------------------------- - if ( $start_from ) + if ( $start_from && 0) { # start_from can be specified as [suite.].testname_prefix my ($suite, $test, $ext)= split_testname($start_from); @@ -749,7 +743,7 @@ sub collect_one_test_case { if ( $suite and $suitename lt $suite){ return; # Skip silently } - if ( $tname lt $test ){ + if ((!$suite || $suitename == $suite) && $tname lt $test ){ return; # Skip silently } } @@ -762,7 +756,7 @@ sub collect_one_test_case { name => "$suitename.$tname", shortname => $tname, path => "$testdir/$filename", - + suite => $suitename, ); my $result_file= "$resdir/$tname.result"; @@ -782,7 +776,9 @@ sub collect_one_test_case { # ---------------------------------------------------------------------- # Skip some tests but include in list, just mark them as skipped # ---------------------------------------------------------------------- - if ( $skip_test_reg and $tname =~ /$skip_test_reg/o ) + my $name= basename($suitename) . ".$tname"; + if ( $skip_test_reg and ($tname =~ /$skip_test_reg/o || + $name =~ /$skip_test/o)) { $tinfo->{'skip'}= 1; return $tinfo; @@ -830,15 +826,6 @@ sub collect_one_test_case { push(@{$tinfo->{'master_opt'}}, @$suite_opts); push(@{$tinfo->{'slave_opt'}}, @$suite_opts); - #----------------------------------------------------------------------- - # Check for test specific config file - #----------------------------------------------------------------------- - my $test_cnf_file= "$testdir/$tname.cnf"; - if ( -f $test_cnf_file) { - # Specifies the configuration file to use for this test - $tinfo->{'template_path'}= $test_cnf_file; - } - # ---------------------------------------------------------------------- # Check for test specific config file # ---------------------------------------------------------------------- @@ -891,17 +878,22 @@ sub collect_one_test_case { if ( -f "$testdir/$tname.slave-mi"); - tags_from_test_file($tinfo,"$testdir/${tname}.test"); + my @source_files = tags_from_test_file($tinfo,"$testdir/${tname}.test"); + + # Get default storage engine from suite.opt file + + if (defined $suite_opts && + "@$suite_opts" =~ "default-storage-engine=\s*([^\s]*)") + { + $local_default_storage_engine= $1; + } - if ( defined $default_storage_engine ) + if ( defined $local_default_storage_engine ) { # Different default engine is used # tag test to require that engine $tinfo->{'ndb_test'}= 1 - if ( $default_storage_engine =~ /^ndb/i ); - - $tinfo->{'innodb_test'}= 1 - if ( $default_storage_engine =~ /^innodb/i ); + if ( $local_default_storage_engine =~ /^ndb/i ); } @@ -949,69 +941,32 @@ sub collect_one_test_case { } } - if ($tinfo->{'federated_test'}) - { - # This is a test that needs federated, enable it - push(@{$tinfo->{'master_opt'}}, "--loose-federated"); - push(@{$tinfo->{'slave_opt'}}, "--loose-federated"); - } - - if ( $tinfo->{'innodb_test'} ) - { - # This is a test that needs innodb - if ( $::mysqld_variables{'innodb'} eq "OFF" || - ! exists $::mysqld_variables{'innodb'} ) - { - # innodb is not supported, skip it - $tinfo->{'skip'}= 1; - # This comment is checked for running with innodb plugin (see above), - # please keep that in mind if changing the text. - $tinfo->{'comment'}= "No innodb support"; - # But continue processing if we may run it with innodb plugin - return $tinfo unless $do_innodb_plugin; - } - } - elsif ($default_myisam) - { - # This is a temporary fix to allow non-innodb tests to run even if - # the default storage engine is innodb. - push(@{$tinfo->{'master_opt'}}, "--default-storage-engine=MyISAM"); - push(@{$tinfo->{'slave_opt'}}, "--default-storage-engine=MyISAM"); - } - - if ( $tinfo->{'need_binlog'} ) + if ( $tinfo->{'rpl_test'} ) { - if (grep(/^--skip-log-bin/, @::opt_extra_mysqld_opt) ) + if ( $skip_rpl ) { $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "Test needs binlog"; + $tinfo->{'comment'}= "No replication tests(--skip-rpl)"; return $tinfo; } } - else - { - # Test does not need binlog, add --skip-binlog to - # the options used when starting - push(@{$tinfo->{'master_opt'}}, "--loose-skip-log-bin"); - push(@{$tinfo->{'slave_opt'}}, "--loose-skip-log-bin"); - } - if ( $tinfo->{'rpl_test'} ) + if ( $::opt_embedded_server ) { - if ( $skip_rpl ) + if ( $tinfo->{'not_embedded'} ) { $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "No replication tests(--skip-rpl)"; + $tinfo->{'comment'}= "Not run for embedded server"; return $tinfo; } } - if ( $::opt_embedded_server ) + if ( $tinfo->{'not_valgrind'} ) { - if ( $tinfo->{'not_embedded'} ) + if ( $::opt_valgrind_mysqld ) { $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "Not run for embedded server"; + $tinfo->{'comment'}= "Not compatible with Valgrind testing"; return $tinfo; } } @@ -1056,26 +1011,49 @@ sub collect_one_test_case { $tinfo->{template_path}= $config; } - # Set extra config file to use - if (defined $defaults_extra_file) { - $tinfo->{extra_template_path}= $defaults_extra_file; + if ( $tinfo->{'example_plugin_test'} ) + { + if ( !$ENV{'HA_EXAMPLE_SO'} ) + { + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= "Test requires the 'example' plugin"; + return $tinfo; + } + } + + if ( $tinfo->{'oqgraph_test'} ) + { + if ( !$ENV{'GRAPH_ENGINE_SO'} ) + { + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= "Test requires the OQGraph storage engine"; + return $tinfo; + } + } + + if (not ref $::suites{$tinfo->{suite}}) + { + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= $::suites{$tinfo->{suite}}; + return $tinfo; } # ---------------------------------------------------------------------- - # Append mysqld extra options to both master and slave + # Append mysqld extra options to master and slave, as appropriate # ---------------------------------------------------------------------- + for (@source_files) { + s/\.\w+$//; + push @{$tinfo->{master_opt}}, opts_from_file("$_.opt"); + push @{$tinfo->{slave_opt}}, opts_from_file("$_.opt"); + push @{$tinfo->{master_opt}}, opts_from_file("$_-master.opt"); + push @{$tinfo->{slave_opt}}, opts_from_file("$_-slave.opt"); + } + push(@{$tinfo->{'master_opt'}}, @::opt_extra_mysqld_opt); push(@{$tinfo->{'slave_opt'}}, @::opt_extra_mysqld_opt); - # ---------------------------------------------------------------------- - # Add master opts, extra options only for master - # ---------------------------------------------------------------------- - process_opts_file($tinfo, "$testdir/$tname-master.opt", 'master_opt'); - - # ---------------------------------------------------------------------- - # Add slave opts, list of extra option only for slave - # ---------------------------------------------------------------------- - process_opts_file($tinfo, "$testdir/$tname-slave.opt", 'slave_opt'); + process_opts($tinfo, 'master_opt'); + process_opts($tinfo, 'slave_opt'); return $tinfo; } @@ -1085,19 +1063,6 @@ sub collect_one_test_case { # the specified value in "tinfo" my @tags= ( - ["include/have_binlog_format_row.inc", "binlog_formats", ["row"]], - ["include/have_binlog_format_statement.inc", "binlog_formats", ["statement"]], - ["include/have_binlog_format_mixed.inc", "binlog_formats", ["mixed"]], - ["include/have_binlog_format_mixed_or_row.inc", - "binlog_formats", ["mixed", "row"]], - ["include/have_binlog_format_mixed_or_statement.inc", - "binlog_formats", ["mixed", "statement"]], - ["include/have_binlog_format_row_or_statement.inc", - "binlog_formats", ["row", "statement"]], - - ["include/have_log_bin.inc", "need_binlog", 1], - - ["include/have_innodb.inc", "innodb_test", 1], ["include/big_test.inc", "big_test", 1], ["include/have_debug.inc", "need_debug", 1], ["include/have_ndb.inc", "ndb_test", 1], @@ -1105,8 +1070,10 @@ my @tags= ["include/master-slave.inc", "rpl_test", 1], ["include/ndb_master-slave.inc", "rpl_test", 1], ["include/ndb_master-slave.inc", "ndb_test", 1], - ["federated.inc", "federated_test", 1], ["include/not_embedded.inc", "not_embedded", 1], + ["include/not_valgrind.inc", "not_valgrind", 1], + ["include/have_example_plugin.inc", "example_plugin_test", 1], + ["include/have_oqgraph_engine.inc", "oqgraph_test", 1], ["include/have_ssl.inc", "need_ssl", 1], ); @@ -1116,6 +1083,7 @@ sub tags_from_test_file { my $file= shift; #mtr_verbose("$file"); my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!"); + my @all_files=($file); while ( my $line= <$F> ) { @@ -1151,13 +1119,13 @@ sub tags_from_test_file { # Only source the file if it exists, we may get # false positives in the regexes above if someone # writes "source nnnn;" in a test case(such as mysqltest.test) - tags_from_test_file($tinfo, $sourced_file); + unshift @all_files, tags_from_test_file($tinfo, $sourced_file); last; } } } - } + @all_files; } sub unspace { @@ -1170,6 +1138,9 @@ sub unspace { sub opts_from_file ($) { my $file= shift; + local $_; + + return () unless -f $file; open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!"); my @args; @@ -1211,7 +1182,7 @@ sub opts_from_file ($) { } } close FILE; - return \@args; + return @args; } sub print_testcases { @@ -1226,3 +1197,4 @@ sub print_testcases { 1; + diff --git a/mysql-test/lib/mtr_gcov.pl b/mysql-test/lib/mtr_gcov.pl index f531889b08d..2f211b7566d 100644 --- a/mysql-test/lib/mtr_gcov.pl +++ b/mysql-test/lib/mtr_gcov.pl @@ -20,6 +20,8 @@ use strict; +our $basedir; + sub gcov_prepare ($) { my ($dir)= @_; print "Purging gcov information from '$dir'...\n"; @@ -42,7 +44,7 @@ sub gcov_collect ($$$) { # Get current directory to return to later. my $start_dir= cwd(); - print "Collecting source coverage info using '$gcov'...\n"; + print "Collecting source coverage info using '$gcov'...$basedir\n"; -f "$start_dir/$gcov_msg" and unlink("$start_dir/$gcov_msg"); -f "$start_dir/$gcov_err" and unlink("$start_dir/$gcov_err"); @@ -62,6 +64,8 @@ sub gcov_collect ($$$) { $dir_reported= 1; } system("$gcov $f 2>>$start_dir/$gcov_err >>$start_dir/$gcov_msg"); + system("perl", "$basedir/mysql-test/lib/process-purecov-annotations.pl", "$f.gcov"); + } chdir($start_dir); } diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index 32960d866ce..388d252502a 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -198,6 +198,26 @@ sub mtr_milli_sleep ($) { select(undef, undef, undef, ($millis/1000)); } +sub mtr_wait_lock_file { + die "usage: mtr_wait_lock_file(path_to_file, keep_alive)" unless @_ == 2; + my ($file, $keep_alive)= @_; + my $waited= 0; + my $msg_counter= $keep_alive; + + while ( -e $file) + { + if ($keep_alive && !$msg_counter) + { + print "\n-STOPPED- [pass] ".$keep_alive."\n"; + $msg_counter= $keep_alive; + } + mtr_milli_sleep(1000); + $waited= 1; + $msg_counter--; + } + return ($waited); +} + # Simple functions to start and check timers (have to be actively polled) # Timer can be "killed" by setting it to 0 diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 77f6920771d..a90c367178d 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -61,14 +61,10 @@ sub _name { sub _mtr_report_test_name ($) { my $tinfo= shift; - my $tname= $tinfo->{name}; + my $tname= $tinfo->fullname(); return unless defined $verbose; - # Add combination name if any - $tname.= " '$tinfo->{combination}'" - if defined $tinfo->{combination}; - print _name(). _timestamp(); printf "%-40s ", $tname; my $worker = $tinfo->{worker}; @@ -222,8 +218,11 @@ sub mtr_report_test ($) { } -sub mtr_report_stats ($$;$) { - my ($prefix, $tests, $dont_error)= @_; +sub mtr_report_stats ($$$$) { + my $prefix= shift; + my $fail= shift; + my $tests= shift; + my $extra_warnings= shift; # ---------------------------------------------------------------------- # Find out how we where doing @@ -297,16 +296,14 @@ sub mtr_report_stats ($$;$) { time - $BASETIME, "seconds executing testcases"); } - my $warnlog= "$::opt_vardir/log/warnings"; - if ( -f $warnlog ) + if ( ! $::glob_use_running_server && !$::opt_extern && -f $warnlog) { mtr_warning("Got errors/warnings while running tests, please examine", "'$warnlog' for details."); - } + } print "\n"; - # Print a list of check_testcases that failed(if any) if ( $::opt_check_testcases ) { @@ -376,9 +373,26 @@ sub mtr_report_stats ($$;$) { print "All $tot_tests tests were successful.\n\n"; } + if (@$extra_warnings) + { + print <<MSG; +Errors/warnings were found in logfiles during server shutdown after running the +following sequence(s) of tests: +MSG + print " $_\n" for @$extra_warnings; + } + if ( $tot_failed != 0 || $found_problems) { - mtr_error("there were failing test cases") unless $dont_error; + mtr_error("there were failing test cases"); + } + elsif (@$extra_warnings) + { + mtr_error("There where errors/warnings in server logs after running test cases."); + } + elsif ($fail) + { + mtr_error("Test suite failure, see messages above for possible cause(s)."); } } diff --git a/mysql-test/lib/process-purecov-annotations.pl b/mysql-test/lib/process-purecov-annotations.pl new file mode 100755 index 00000000000..d533bd02fd6 --- /dev/null +++ b/mysql-test/lib/process-purecov-annotations.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl +# -*- cperl -*- + +# This script processes a .gcov coverage report to honor purecov +# annotations: lines marked as inspected or as deadcode are changed +# from looking like lines with code that was never executed to look +# like lines that have no executable code. + +use strict; +use warnings; + +foreach my $in_file_name ( @ARGV ) +{ + my $out_file_name=$in_file_name . ".tmp"; + my $skipping=0; + + open(IN, "<", $in_file_name) || next; + open(OUT, ">", $out_file_name); + while(<IN>) + { + my $line= $_; + my $check= $line; + + # process purecov: start/end multi-blocks + my $started=0; + my $ended= 0; + while (($started=($check =~ s/purecov: *begin *(deadcode|inspected)//)) || + ($ended=($check =~ s/purecov: *end//))) + { + $skipping= $skipping + $started - $ended; + } + if ($skipping < 0) + { + print OUT "WARNING: #####: incorrect order of purecov begin/end annotations\n"; + $skipping= 0; + } + + # Besides purecov annotations, also remove uncovered code mark from cases + # like the following: + # + # -: 211:*/ + # -: 212:class Field_value : public Value_dep + # #####: 213:{ + # -: 214:public: + # + # I have no idea why would gcov think there is uncovered code there + # + my @arr= split(/:/, $line); + if ($skipping || $line =~ /purecov: *(inspected|deadcode)/ || + $arr[2] =~ m/^{ *$/) + { + # Change '####' to '-'. + $arr[0] =~ s/#####/ -/g; + $line= join(":", @arr); + } + print OUT $line; + } + close(IN); + close(OUT); + system("mv", "-f", $out_file_name, $in_file_name); +} + + diff --git a/mysql-test/lib/v1/mtr_process.pl b/mysql-test/lib/v1/mtr_process.pl index 4a4e342bff6..33a39d1f0b6 100644 --- a/mysql-test/lib/v1/mtr_process.pl +++ b/mysql-test/lib/v1/mtr_process.pl @@ -475,12 +475,6 @@ sub mtr_kill_leftovers () { } } } - else - { - mtr_warning("Found non pid file $elem in $rundir") - if -f "$rundir/$elem"; - next; - } } closedir(RUNDIR); @@ -887,15 +881,33 @@ sub check_expected_crash_and_restart($) mtr_verbose("$mysqld->{'type'} $mysqld->{'idx'} exited, pid: $ret_pid"); $mysqld->{'pid'}= 0; - # Check if crash expected and restart if it was + # Check if crash expected, and restart if it was my $expect_file= "$::opt_vardir/tmp/" . "$mysqld->{'type'}" . "$mysqld->{'idx'}" . ".expect"; - if ( -f $expect_file ) + while ( 1 ) { - mtr_verbose("Crash was expected, file $expect_file exists"); - mysqld_start($mysqld, $mysqld->{'start_opts'}, - $mysqld->{'start_slave_master_info'}); - unlink($expect_file); + if ( -f $expect_file ) + { + mtr_verbose("Crash was expected, file $expect_file exists"); + my $expect_file_handler; + open($expect_file_handler, "<$expect_file") or die; + my @expect_lines= <$expect_file_handler>; + close $expect_file_handler; + # look at most recent order by the test + my $expect_content= pop @expect_lines; + chomp $expect_content; + if ( $expect_content =~ /^wait/ ) + { + mtr_verbose("Test asks that we wait before restart"); + # Millisceond sleep emulated with select + select(undef, undef, undef, (0.1)); + next; + } + unlink($expect_file); + mysqld_start($mysqld, $mysqld->{'start_opts'}, + $mysqld->{'start_slave_master_info'}); + } + last; } return; @@ -915,8 +927,8 @@ sub check_expected_crash_and_restart($) if ( -f $expect_file ) { mtr_verbose("Crash was expected, file $expect_file exists"); - ndbmgmd_start($cluster); unlink($expect_file); + ndbmgmd_start($cluster); } return; } @@ -934,9 +946,9 @@ sub check_expected_crash_and_restart($) if ( -f $expect_file ) { mtr_verbose("Crash was expected, file $expect_file exists"); + unlink($expect_file); ndbd_start($cluster, $ndbd->{'idx'}, $ndbd->{'start_extra_args'}); - unlink($expect_file); } return; } diff --git a/mysql-test/lib/v1/mtr_report.pl b/mysql-test/lib/v1/mtr_report.pl index 84784ed19d4..dde093ff674 100644 --- a/mysql-test/lib/v1/mtr_report.pl +++ b/mysql-test/lib/v1/mtr_report.pl @@ -220,7 +220,7 @@ sub mtr_report_stats ($) { # the "var/log/*.err" files. We save this info in "var/log/warnings" # ---------------------------------------------------------------------- - if ( ! $::glob_use_running_server ) + if ( ! $::glob_use_running_server && !$::opt_extern) { # Save and report if there was any fatal warnings/errors in err logs @@ -387,11 +387,10 @@ sub mtr_report_stats ($) { (/Failed during slave.*thread initialization/ )) or - # rpl_temporary has an error on slave that can be ignored - ($testname eq 'rpl.rpl_temporary' and - (/Slave: Can\'t find record in \'user\' Error_code: 1032/ - )) or - + # rpl_temporary has an error on slave that can be ignored + ($testname eq 'rpl.rpl_temporary' and + (/Slave: Can\'t find record in \'user\' Error_code: 1032/ + )) or # Test case for Bug#31590 produces the following error: /Out of sort memory; increase server sort buffer size/ or @@ -404,8 +403,18 @@ sub mtr_report_stats ($) { # When trying to set lower_case_table_names = 2 # on a case sensitive file system. Bug#37402. - /lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive. Now setting lower_case_table_names to 0 to avoid future problems./ - ) + /lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive. Now setting lower_case_table_names to 0 to avoid future problems./ or + + # maria-recovery.test has warning about missing log file + /File '.*maria_log.000.*' not found \(Errcode: 2\)/ or + # and about marked-corrupted table + /Table '..mysqltest.t_corrupted1' is crashed, skipping it. Please repair it with maria_chk -r/ or + # maria-recover.test corrupts tables on purpose + /Checking table: '..mysqltest.t_corrupted2'/ or + /Recovering table: '..mysqltest.t_corrupted2'/ or + /Table '..mysqltest.t_corrupted2' is marked as crashed and should be repaired/ or + /Incorrect key file for table '..mysqltest.t_corrupted2.MAI'; try to repair it/ + ) { next; # Skip these lines } diff --git a/mysql-test/lib/v1/mysql-test-run.pl b/mysql-test/lib/v1/mysql-test-run.pl index 4e4f09981cc..e4743c73d6b 100755 --- a/mysql-test/lib/v1/mysql-test-run.pl +++ b/mysql-test/lib/v1/mysql-test-run.pl @@ -134,8 +134,9 @@ our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; our $default_vardir; our $opt_usage; +our $opt_list_options; our $opt_suites; -our $opt_suites_default= "main,binlog,rpl,rpl_ndb,ndb"; # Default suites to run +our $opt_suites_default= "main,binlog,rpl,rpl_ndb,ndb,maria"; # Default suites to run our $opt_script_debug= 0; # Script debugging, enable with --script-debug our $opt_verbose= 0; # Verbose output, enable with --verbose @@ -171,6 +172,7 @@ our @opt_combinations; our $opt_skip_combination; our @opt_extra_mysqld_opt; +our @opt_extra_mysqltest_opt; our $opt_compress; our $opt_ssl; @@ -430,7 +432,7 @@ sub main () { my $tests= collect_test_cases($opt_suites); # Turn off NDB and other similar options if no tests use it - my ($need_ndbcluster,$need_im); + my ($need_ndbcluster,$need_im, $need_debug); foreach my $test (@$tests) { next if $test->{skip}; @@ -438,6 +440,7 @@ sub main () { if (!$opt_extern) { $need_ndbcluster||= $test->{ndb_test}; + $need_debug||=$test->{need_debug}; $need_im||= $test->{component_id} eq 'im'; # Count max number of slaves used by a test case @@ -463,6 +466,11 @@ sub main () { $opt_skip_ndbcluster_slave= 1; } + if ( !$need_debug && !$opt_debug) + { + $opt_debug=0; + } + # Check if slave cluster can be skipped if ($max_slave_num == 0) { @@ -547,7 +555,7 @@ sub command_line_setup () { ); Getopt::Long::Configure("pass_through"); - GetOptions( + my %options=( # Control what engine/variation to run 'embedded-server' => \$opt_embedded_server, 'ps-protocol' => \$opt_ps_protocol, @@ -599,6 +607,9 @@ sub command_line_setup () { # Extra options used when starting mysqld 'mysqld=s' => \@opt_extra_mysqld_opt, + # Extra options used when starting mysqld + 'mysqltest=s' => \@opt_extra_mysqltest_opt, + # Run test on running server 'extern' => \$opt_extern, 'ndb-connectstring=s' => \$opt_ndbconnectstring, @@ -682,9 +693,13 @@ sub command_line_setup () { (map { $_ => \&warn_about_removed_option } @removed_options), 'help|h' => \$opt_usage, - ) or usage("Can't read options"); + 'list-options' => \$opt_list_options, + ); + + GetOptions(%options) or usage("Can't read options"); usage("") if $opt_usage; + list_options(\%options) if $opt_list_options; $glob_scriptname= basename($0); @@ -990,7 +1005,7 @@ sub command_line_setup () { # -------------------------------------------------------------------------- if ($opt_extern) { - mtr_report("Disable instance manager when running with extern mysqld"); + # mtr_report("Disable instance manager when running with extern mysqld"); $opt_skip_im= 1; } elsif ( $mysql_version_id < 50000 ) @@ -1365,19 +1380,6 @@ sub command_line_setup () { $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log"; $path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/"; - - if ( $opt_valgrind and $opt_debug ) - { - # 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 - foreach my $mysqld (@{$master}, @{$slave}) - { - my $sidx= $mysqld->{idx} ? "$mysqld->{idx}" : ""; - $mysqld->{path_myerr}= - "$opt_vardir/log/" . $mysqld->{type} . "$sidx.trace"; - } - } } # @@ -2136,7 +2138,10 @@ sub environment_setup () { $ENV{'MYSQL_UPGRADE'}= mysql_upgrade_arguments(); } - $ENV{'MYSQL_FIX_PRIVILEGE_TABLES'}= $file_mysql_fix_privilege_tables; + if ( !$opt_extern ) + { + $ENV{'MYSQL_FIX_PRIVILEGE_TABLES'}= $file_mysql_fix_privilege_tables; + } # ---------------------------------------------------- # Setup env so childs can execute my_print_defaults @@ -2153,6 +2158,7 @@ sub environment_setup () { # ---------------------------------------------------- $ENV{'MY_PERROR'}= mtr_native_path($exe_perror); +#warning remove the below # ---------------------------------------------------- # Add the path where mysqld will find udf_example.so # ---------------------------------------------------- @@ -2186,6 +2192,22 @@ sub environment_setup () { "$glob_bindir/myisam/myisampack")); # ---------------------------------------------------- + # Setup env so childs can execute aria_pack and aria_chk + # ---------------------------------------------------- + $ENV{'ARIA_CHK'}= mtr_native_path(mtr_exe_maybe_exists( + vs_config_dirs('storage/maria', 'aria_chk'), + vs_config_dirs('maria', 'aria_chk'), + "$path_client_bindir/aria_chk", + "$glob_basedir/storage/maria/aria_chk", + "$glob_basedir/maria/aria_chk")); + $ENV{'ARIA_PACK'}= mtr_native_path(mtr_exe_maybe_exists( + vs_config_dirs('storage/maria', 'aria_pack'), + vs_config_dirs('maria', 'aria_pack'), + "$path_client_bindir/aria_pack", + "$glob_basedir/storage/maria/aria_pack", + "$glob_basedir/maria/aria_pack")); + + # ---------------------------------------------------- # We are nice and report a bit about our settings # ---------------------------------------------------- if (!$opt_extern) @@ -2430,6 +2452,25 @@ sub setup_vardir() { { unlink($name); } + if ( $opt_valgrind and $opt_debug ) + { + # 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 + foreach my $mysqld (@{$master}, @{$slave}) + { + my $sidx= $mysqld->{idx} ? "$mysqld->{idx}" : ""; + my $trace_name= "$opt_vardir/log/" . $mysqld->{type} . "$sidx.trace"; + open(LOG, ">$mysqld->{path_myerr}") or die "Can't create $mysqld->{path_myerr}\n"; + print LOG " +NOTE: When running with --valgrind --debug the output from the .err file is +stored together with the trace file to make it easier to find the exact +position for valgrind errors. +See trace file $trace_name.\n"; + close(LOG); + $mysqld->{path_myerr}= $trace_name; + } + } } @@ -2882,7 +2923,7 @@ sub run_benchmarks ($) { if ( ! $benchmark ) { - mtr_add_arg($args, "--log"); + mtr_add_arg($args, "--general-log"); mtr_run("$glob_mysql_bench_dir/run-all-tests", $args, "", "", "", ""); # FIXME check result code?! } @@ -3106,17 +3147,26 @@ sub install_db ($$) { mtr_report("Installing \u$type Database"); - my $args; + my $cmd_args; mtr_init_args(\$args); mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--bootstrap"); mtr_add_arg($args, "--basedir=%s", $path_my_basedir); mtr_add_arg($args, "--datadir=%s", $data_dir); 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=."); mtr_add_arg($args, "--core-file"); + # + # Setup args for bootstrap.test + # + mtr_init_args(\$cmd_args); + mtr_add_arg($cmd_args, "--loose-skip-aria"); + if ( $opt_debug ) { mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap_%s.trace", @@ -3145,7 +3195,8 @@ sub install_db ($$) { # ---------------------------------------------------------------------- # export MYSQLD_BOOTSTRAP_CMD variable containing <path>/mysqld <args> # ---------------------------------------------------------------------- - $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args); + $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args) . + " " . join(" ", @$cmd_args); # ---------------------------------------------------------------------- # Create the bootstrap.sql file @@ -3323,6 +3374,24 @@ sub run_testcase_check_skip_test($) my ($tinfo)= @_; # ---------------------------------------------------------------------- + # Skip some tests silently + # ---------------------------------------------------------------------- + + if ( $::opt_start_from ) + { + if ($tinfo->{'name'} eq $::opt_start_from ) + { + ## Found parting test. Run this test and all tests after this one + $::opt_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 @@ -3904,17 +3973,22 @@ sub mysqld_arguments ($$$$) { mtr_add_arg($args, "%s--datadir=%s", $prefix, $mysqld->{'path_myddir'}); + mtr_add_arg($args, "%s--disable-sync-frm", $prefix); # Faster test - if ( $mysql_version_id >= 50106 ) + if (!$opt_extern and $mysql_version_id >= 50106 ) { # Turn on logging to bothe tables and file mtr_add_arg($args, "%s--log-output=table,file", $prefix); } my $log_base_path= "$opt_vardir/log/$mysqld->{'type'}$sidx"; - mtr_add_arg($args, "%s--log=%s.log", $prefix, $log_base_path); + mtr_add_arg($args, "%s--general-log-file=%s.log", + $prefix, $log_base_path); + mtr_add_arg($args, "%s--general-log", $prefix); mtr_add_arg($args, - "%s--log-slow-queries=%s-slow.log", $prefix, $log_base_path); + "%s--slow-query-log-file=%s-slow.log", + $prefix, $log_base_path); + mtr_add_arg($args, "%s--slow-query-log", $prefix); # Check if "extra_opt" contains --skip-log-bin my $skip_binlog= grep(/^--skip-log-bin/, @$extra_opt, @opt_extra_mysqld_opt); @@ -4038,10 +4112,17 @@ sub mysqld_arguments ($$$$) { } # end slave - if ( $opt_debug ) + if ( $debug_compiled_binaries && defined $opt_debug ) { - mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/%s%s.trace", - $prefix, $path_vardir_trace, $mysqld->{'type'}, $sidx); + if ( $opt_debug ) + { + mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/%s%s.trace", + $prefix, $path_vardir_trace, $mysqld->{'type'}, $sidx); + } + else + { + mtr_add_arg($args, "--disable-debug"); + } } mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix); @@ -4894,6 +4975,11 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--skip-ssl"); } + foreach my $arg ( @opt_extra_mysqltest_opt ) + { + mtr_add_arg($args, "%s", $arg); + } + # ---------------------------------------------------------------------- # If embedded server, we create server args to give mysqltest to pass on # ---------------------------------------------------------------------- @@ -5009,13 +5095,9 @@ sub gdb_arguments { 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, <<EOGDB ); +set args $str +EOGDB } if ( $opt_manual_gdb ) @@ -5075,11 +5157,7 @@ sub ddd_arguments { # 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"); + "set args $str\n"); } if ( $opt_manual_ddd ) @@ -5367,3 +5445,16 @@ HERE mtr_exit(1); } + +sub list_options ($) { + my $hash= shift; + + for (keys %$hash) { + s/(=.*|!)$//; + s/\|/\n--/g; + print "--$_\n"; + } + + mtr_exit(1); +} + |