diff options
author | unknown <msvensson@shellback.(none)> | 2007-11-23 13:29:31 +0100 |
---|---|---|
committer | unknown <msvensson@shellback.(none)> | 2007-11-23 13:29:31 +0100 |
commit | 59574a6e601d6725492d9283a3d386df16eace32 (patch) | |
tree | a60b4eee99c0a879a4db340a9ad0ece977253c20 /mysql-test/lib | |
parent | de9bc5c4b07fb020af4b6434e9c2b02ce3474bf8 (diff) | |
download | mariadb-git-59574a6e601d6725492d9283a3d386df16eace32.tar.gz |
WL#3949 Test should set binlog format dnamically
- Reorganize collect a little to make it easier to apply optimizations
and settings to collected test cases.
- Add suite/rpl/combination file
- Rename include/set_binlog_format_x.inc to .sql since thay are run by "mysql"
mysql-test/include/set_binlog_format_mixed.sql:
Rename: mysql-test/include/set_binlog_format_mixed.inc -> mysql-test/include/set_binlog_format_mixed.sql
mysql-test/include/set_binlog_format_row.sql:
Rename: mysql-test/include/set_binlog_format_row.inc -> mysql-test/include/set_binlog_format_row.sql
mysql-test/include/set_binlog_format_statement.sql:
Rename: mysql-test/include/set_binlog_format_statement.inc -> mysql-test/include/set_binlog_format_statement.sql
mysql-test/lib/mtr_cases.pl:
Reorganize code to
- collect a suite
- multiply the tests in the suite with any combinations the suite has
- optimize the suite by skipping test not supported with current settings
Use My::Config to read combinations file in my.cnf file format, this
allowas a "short name" to be used for the combination instead of
the full name wich is set to the extra arguments the combination applies
Add function 'print_testcase' that can be used to print the testcases
during different stages of the collect phase
mysql-test/lib/mtr_report.pl:
Print <testname> '<combination>' if combination is set
mysql-test/mysql-test-run.pl:
Add comments, fix indentation
Rename .in to .sql files
Only set binlog format dynamicall for master, slav is always restarted
mysql-test/lib/My/Config.pm:
New BitKeeper file ``mysql-test/lib/My/Config.pm''
mysql-test/suite/rpl/combinations:
New BitKeeper file ``mysql-test/suite/rpl/combinations''
Diffstat (limited to 'mysql-test/lib')
-rw-r--r-- | mysql-test/lib/My/Config.pm | 422 | ||||
-rw-r--r-- | mysql-test/lib/mtr_cases.pl | 327 | ||||
-rw-r--r-- | mysql-test/lib/mtr_report.pl | 8 |
3 files changed, 601 insertions, 156 deletions
diff --git a/mysql-test/lib/My/Config.pm b/mysql-test/lib/My/Config.pm new file mode 100644 index 00000000000..5491e341ddc --- /dev/null +++ b/mysql-test/lib/My/Config.pm @@ -0,0 +1,422 @@ +# -*- cperl -*- + +package My::Config::Option; + +use strict; +use warnings; + + +sub new { + my ($class, $option_name, $option_value)= @_; + my $self= bless { name => $option_name, + value => $option_value + }, $class; + return $self; +} + + +sub name { + my ($self)= @_; + return $self->{name}; +} + + +sub value { + my ($self)= @_; + return $self->{value}; +} + + +package My::Config::Group; + +use strict; +use warnings; + + +sub new { + my ($class, $group_name)= @_; + my $self= bless { name => $group_name, + options => [], + options_by_name => {}, + }, $class; + return $self; +} + + +sub insert { + my ($self, $option_name, $value, $if_not_exist)= @_; + my $option= $self->option($option_name); + if (defined($option) and !$if_not_exist) { + $option->{value}= $value; + } + else { + my $option= My::Config::Option->new($option_name, $value); + # Insert option in list + push(@{$self->{options}}, $option); + # Insert option in hash + $self->{options_by_name}->{$option_name}= $option; + } + return $option; +} + +sub remove { + my ($self, $option_name)= @_; + + # Check that option exists + my $option= $self->option($option_name); + + return undef unless defined $option; + + # Remove from the hash + delete($self->{options_by_name}->{$option_name}) or die; + + # Remove from the array + @{$self->{options}}= grep { $_->name ne $option_name } @{$self->{options}}; + + return $option; +} + + +sub options { + my ($self)= @_; + return @{$self->{options}}; +} + + +sub name { + my ($self)= @_; + return $self->{name}; +} + + +# +# Return a specific option in the group +# +sub option { + my ($self, $option_name)= @_; + + return $self->{options_by_name}->{$option_name}; +} + + +# +# Return a specific value for an option in the group +# +sub value { + my ($self, $option_name)= @_; + my $option= $self->option($option_name); + + die "No option named '$option_name' in this group" + if ! defined($option); + + return $option->value(); +} + + +package My::Config; + +use strict; +use warnings; +use IO::File; +use File::Basename; + +# +# Constructor for My::Config +# - represents a my.cnf config file +# +# Array of arrays +# +sub new { + my ($class, $path)= @_; + my $group_name= undef; + + my $self= bless { groups => [] }, $class; + my $F= IO::File->new($path, "<") + or die "Could not open '$path': $!"; + + while ( my $line= <$F> ) { + chomp($line); + + # [group] + if ( $line =~ /\[(.*)\]/ ) { + # New group found + $group_name= $1; + #print "group: $group_name\n"; + + $self->insert($group_name, undef, undef); + } + + # Magic #! comments + elsif ( $line =~ /^#\!/) { + my $magic= $line; + die "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; + } + + # Empty lines + elsif ( $line =~ /^$/ ) { + # Skip empty lines + next; + } + + # !include <filename> + elsif ( $line =~ /^\!include\s*(.*?)\s*$/ ) { + my $include_file_name= dirname($path)."/".$1; + # Check that the file exists + die "The include file '$include_file_name' does not exist" + unless -f $include_file_name; + + $self->append(My::Config->new($include_file_name)); + } + + # <option> + elsif ( $line =~ /^([\@\w-]+)\s*$/ ) { + my $option= $1; + + die "Found option '$option' outside of group" + unless $group_name; + + #print "$option\n"; + $self->insert($group_name, $option, undef); + } + + # <option>=<value> + elsif ( $line =~ /^([\@\w-]+)\s*=\s*(.*?)\s*$/ ) { + my $option= $1; + my $value= $2; + + die "Found option '$option=$value' outside of group" + unless $group_name; + + #print "$option=$value\n"; + $self->insert($group_name, $option, $value); + } else { + die "Unexpected line '$line' found in '$path'"; + } + + } + undef $F; # Close the file + + return $self; +} + +# +# Insert a new group if it does not already exist +# and add option if defined +# +sub insert { + my ($self, $group_name, $option, $value, $if_not_exist)= @_; + my $group; + + # Create empty array for the group if it doesn't exist + if ( !$self->group_exists($group_name) ) { + $group= $self->_group_insert($group_name); + } + else { + $group= $self->group($group_name); + } + + if ( defined $option ) { + #print "option: $option, value: $value\n"; + + # Add the option to the group + $group->insert($option, $value, $if_not_exist); + } +} + +# +# Remove a option, given group and option name +# +sub remove { + my ($self, $group_name, $option_name)= @_; + my $group= $self->group($group_name); + + die "group '$group_name' does not exist" + unless defined($group); + + $group->remove($option_name) or + die "option '$option_name' does not exist"; +} + + + +# +# Check if group with given name exists in config +# +sub group_exists { + my ($self, $group_name)= @_; + + foreach my $group ($self->groups()) { + return 1 if $group->{name} eq $group_name; + } + return 0; +} + + +# +# Insert a new group into config +# +sub _group_insert { + my ($self, $group_name)= @_; + caller eq __PACKAGE__ or die; + + # Check that group does not already exist + die "Group already exists" if $self->group_exists($group_name); + + my $group= My::Config::Group->new($group_name); + push(@{$self->{groups}}, $group); + return $group; +} + + +# +# Append a configuration to current config +# +sub append { + my ($self, $from)= @_; + + foreach my $group ($from->groups()) { + foreach my $option ($group->options()) { + $self->insert($group->name(), $option->name(), $option->value()); + } + + } +} + + +# +# Return a list with all the groups in config +# +sub groups { + my ($self)= @_; + return ( @{$self->{groups}} ); +} + + +# +# Return a list of all the groups in config +# starting with the given string +# +sub like { + my ($self, $prefix)= @_; + return ( grep ( $_->{name} =~ /^$prefix/, $self->groups()) ); +} + + +# +# Return the first group in config +# starting with the given string +# +sub first_like { + my ($self, $prefix)= @_; + return ($self->like($prefix))[0]; +} + + +# +# Return a specific group in the config +# +sub group { + my ($self, $group_name)= @_; + + foreach my $group ( $self->groups() ) { + return $group if $group->{name} eq $group_name; + } + return undef; +} + + +# +# Return a list of all options in a specific group in the config +# +sub options_in_group { + my ($self, $group_name)= @_; + + my $group= $self->group($group_name); + return () unless defined $group; + return $group->options(); +} + + +# +# Return a value given group and option name +# +sub value { + my ($self, $group_name, $option_name)= @_; + my $group= $self->group($group_name); + + die "group '$group_name' does not exist" + unless defined($group); + + my $option= $group->option($option_name); + die "option '$option_name' does not exist" + unless defined($option); + + return $option->value(); +} + + +# +# Check if an option exists +# +sub exists { + my ($self, $group_name, $option_name)= @_; + my $group= $self->group($group_name); + + die "group '$group_name' does not exist" + unless defined($group); + + my $option= $group->option($option_name); + 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 die "Could not open '$path': $!"; + print $F $self; + undef $F; # Close the file +} + +1; diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index d3f4c532b2f..0a58905c26d 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -22,8 +22,11 @@ use File::Basename; use IO::File(); use strict; +use lib "lib/"; +use My::Config; + sub collect_test_cases ($); -sub collect_one_suite ($$); +sub collect_one_suite ($); sub collect_one_test_case ($$$$$$$$$); sub mtr_options_from_test_file($$); @@ -63,7 +66,7 @@ sub collect_test_cases ($) { foreach my $suite (split(",", $suites)) { - collect_one_suite($suite, $cases); + push(@$cases, collect_one_suite($suite)); } @@ -207,16 +210,13 @@ sub split_testname { } -sub collect_one_suite($$) +sub collect_one_suite($) { my $suite= shift; # Test suite name - my $cases= shift; # List of test cases + my @cases; # Array of hash mtr_verbose("Collecting: $suite"); - my $combination_file= "combinations"; - my $combinations = []; - my $suitedir= "$::glob_mysql_test_dir"; # Default if ( $suite ne "main" ) { @@ -224,36 +224,10 @@ sub collect_one_suite($$) "$suitedir/$suite"); mtr_verbose("suitedir: $suitedir"); } - my $combination_file= "$suitedir/$combination_file"; my $testdir= "$suitedir/t"; my $resdir= "$suitedir/r"; - if (!defined $::opt_record and !defined $::opt_skip_combination) - { - if (!@::opt_combination) - { - # Read combinations file - if ( open(COMB,$combination_file) ) - { - while (<COMB>) - { - chomp; - s/\ +/ /g; - push (@$combinations, $_) unless ($_ eq ''); - } - close COMB; - } - } - else - { - # take the combination from command-line - @$combinations = @::opt_combination; - } - } - # Remember last element position - my $begin_index = $#{@$cases} + 1; - # ---------------------------------------------------------------------- # Build a hash of disabled testcases for this suite # ---------------------------------------------------------------------- @@ -328,7 +302,7 @@ sub collect_one_suite($$) } collect_one_test_case($testdir,$resdir,$suite,$tname, - "$tname.$extension",$cases,\%disabled, + "$tname.$extension",\@cases,\%disabled, $component_id,$suite_opts); } } @@ -358,97 +332,154 @@ sub collect_one_suite($$) next if ($do_test and not $tname =~ /$do_test/o); collect_one_test_case($testdir,$resdir,$suite,$tname, - $elem,$cases,\%disabled,$component_id, + $elem,\@cases,\%disabled,$component_id, $suite_opts); } closedir TESTDIR; } + + # Return empty list if no testcases found + return if (@cases == 0); + # ---------------------------------------------------------------------- - # Proccess combinations only if new tests were added + # Read combinations for this suite and build testcases x combinations + # if any combinations exists # ---------------------------------------------------------------------- - if ($combinations && $begin_index <= $#{@$cases}) - { - my $prepared = {}; - my $end_index = $#{@$cases}; - my $is_copy; - # Keep original master/slave options - my @orig_opts; - for (my $idx = $begin_index; $idx <= $end_index; $idx++) - { - foreach my $param (('master_opt','slave_opt','slave_mi')) - { - @{$orig_opts[$idx]{$param}} = @{$cases->[$idx]->{$param}}; + if ( ! $::opt_skip_combination ) + { + my @combinations; + my $combination_file= "$suitedir/combinations"; + print "combination_file: $combination_file\n"; + if (@::opt_combinations) + { + # take the combination from command-line + mtr_verbose("Take the combination from command line"); + foreach my $combination (@::opt_combinations) { + my $comb= {}; + $comb->{name}= $combination; + push(@{$comb->{comb_opt}}, $combination); + push(@combinations, $comb); + } + } + elsif (-f $combination_file ) + { + # Read combinations file in my.cnf format + mtr_verbose("Read combinations file"); + my $config= My::Config->new($combination_file); + + foreach my $group ($config->groups()) { + my $comb= {}; + $comb->{name}= $group->name(); + foreach my $option ( $group->options() ) { + push(@{$comb->{comb_opt}}, $option->name()."=".$option->value()); + } + push(@combinations, $comb); } } - my $comb_index = 1; - # Copy original test cases - foreach my $comb_set (@$combinations) - { - for (my $idx = $begin_index; $idx <= $end_index; $idx++) + + if (@combinations) + { + print " - adding combinations\n"; + #print_testcases(@cases); + + my @new_cases; + foreach my $comb (@combinations) { - my $test = $cases->[$idx]; - my $copied_test = {}; - foreach my $param (keys %{$test}) - { - # Scalar. Copy as is. - $copied_test->{$param} = $test->{$param}; - # Array. Copy reference instead itself - if ($param =~ /(master_opt|slave_opt|slave_mi)/) - { - my $new_arr = []; - @$new_arr = @{$orig_opts[$idx]{$param}}; - $copied_test->{$param} = $new_arr; - } - elsif ($param =~ /combinations/) - { - $copied_test->{$param} = ''; - } - } - if ($is_copy) - { - push(@$cases, $copied_test); - $test = $cases->[$#{@$cases}]; - } - foreach my $comb_opt (split(/ /,$comb_set)) - { - push(@{$test->{'master_opt'}},$comb_opt); - push(@{$test->{'slave_opt'}},$comb_opt); - # Enable rpl if added option is --binlog-format and test case supports that - if ($comb_opt =~ /^--binlog-format=.+$/) - { - my @opt_pairs = split(/=/, $comb_opt); - if (defined $::used_binlog_format) - { - if ($test->{'binlog_format'} ne $::used_binlog_format) - { - $test->{'skip'} = 1; - $test->{'comment'} = "Requiring binlog format ".join(' or ', @{$test->{'sup_binlog_formats'}}); - } - } - else - { - foreach my $binlog_format (@{$test->{'sup_binlog_formats'}}) - { - $test->{'binlog_format'}= $binlog_format if ($binlog_format eq $opt_pairs[1]); - } - if (defined $prepared->{$test->{'name'}.'|'.$test->{'binlog_format'}} and $test->{'skip'} ne 1 ) - { - $test->{'skip'} = 1; - $test->{'comment'} = "Test for binlog format '$test->{'binlog_format'}' already executed"; - } - } - } - } - $prepared->{$test->{'name'}.'|'.$test->{'binlog_format'}}= 1; - $test->{'combination'} = $comb_set; - } - $is_copy = 1; - $comb_index++; - } + foreach my $test (@cases) + { + #print $test->{name}, " ", $comb, "\n"; + my $new_test= {}; + + while (my ($key, $value) = each(%$test)) { + if (ref $value eq "ARRAY") { + push(@{$new_test->{$key}}, @$value); + } else { + $new_test->{$key}= $value; + } + } + + # Append the combination options to master_opt and slave_opt + push(@{$new_test->{master_opt}}, @{$comb->{comb_opt}}); + push(@{$new_test->{slave_opt}}, @{$comb->{comb_opt}}); + + # Add combination name shrt name + $new_test->{combination}= $comb->{name}; + + # Add the new test to new test cases list + push(@new_cases, $new_test); + } + } + #print_testcases(@new_cases); + @cases= @new_cases; + #print_testcases(@cases); + } } - return $cases; + optimize_cases(\@cases); + #print_testcases(@cases); + + return @cases; +} + + +# +# Loop through all test cases +# - optimize which test to run by skipping unnecessary ones +# - update settings if necessary +# +sub optimize_cases { + my ($cases)= @_; + + foreach my $tinfo ( @$cases ) + { + # Replication test needs an adjustment of binlog format + if (mtr_match_prefix($tinfo->{'name'}, "rpl")) + { + + # ======================================================= + # Get binlog-format used by this test from master_opt + # ======================================================= + my $test_binlog_format; + foreach my $opt ( @{$tinfo->{master_opt}} ) { + $test_binlog_format= $test_binlog_format || + mtr_match_prefix($opt, "--binlog-format="); + } + # print $tinfo->{name}." uses ".$test_binlog_format."\n"; + + # ======================================================= + # If a special binlog format was selected with + # --mysqld=--binlog-format=x, skip all test with different + # binlog-format + # ======================================================= + if (defined $::used_binlog_format and + $::used_binlog_format ne $test_binlog_format) + { + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= "Requires --binlog-format='$test_binlog_format'"; + next; + } + + # ======================================================= + # Check that testcase supports the designated binlog-format + # ======================================================= + if ($test_binlog_format and defined $tinfo->{'sup_binlog_formats'} ) + { + my $supported= + grep { $_ eq $test_binlog_format } @{$tinfo->{'sup_binlog_formats'}}; + if ( !$supported ) + { + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= + "Doesn't support --binlog-format='$test_binlog_format'"; + next; + } + } + + # Save binlog format for dynamic switching + $tinfo->{binlog_format}= $test_binlog_format; + } + } } @@ -752,43 +783,6 @@ sub collect_one_test_case($$$$$$$$$) { return; } - # Replication test needs an adjustment of binlog format - if ($tinfo->{'name'} =~ /^rpl/) - { - # Set default binlog format priority - if ($tinfo->{'name'} =~ /^rpl/ and !defined $tinfo->{'sup_binlog_formats'}) - { - if ($::mysql_version_id >= 50100) - { - $tinfo->{'sup_binlog_formats'} = ["mixed", "row", "statement"]; - } - else - { - $tinfo->{'sup_binlog_formats'} = ["statement", "row"]; - } - } - # Check that a test supports binlog format defined via --binlog-format - if (defined $::used_binlog_format) - { - # Try to find a supported binlog formats - foreach my $binlog_format (@{$tinfo->{'sup_binlog_formats'}}) - { - $tinfo->{'binlog_format'}= $binlog_format unless ($binlog_format ne $::used_binlog_format); - } - # Skip a test because - if (!defined $tinfo->{'binlog_format'}) - { - $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "Requiring binlog format ".join(' or ', @{$tinfo->{'sup_binlog_formats'}}); - return; - } - } - else - { - $tinfo->{'binlog_format'}= $tinfo->{'sup_binlog_formats'}->[0]; - } - } - if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries ) { $tinfo->{'skip'}= 1; @@ -870,11 +864,15 @@ our @tags= ["include/have_innodb.inc", "innodb_test", 1], ["include/have_binlog_format_row.inc", "sup_binlog_formats", ["row"]], ["include/have_log_bin.inc", "need_binlog", 1], - ["include/have_binlog_format_statement.inc", "sup_binlog_formats", ["statement"]], + ["include/have_binlog_format_statement.inc", + "sup_binlog_formats", ["statement"]], ["include/have_binlog_format_mixed.inc", "sup_binlog_formats", ["mixed"]], - ["include/have_binlog_format_mixed_or_row.inc", "sup_binlog_formats", ["mixed","row"]], - ["include/have_binlog_format_mixed_or_statement.inc", "sup_binlog_formats", ["mixed","statement"]], - ["include/have_binlog_format_row_or_statement.inc", "sup_binlog_formats", ["row","statement"]], + ["include/have_binlog_format_mixed_or_row.inc", + "sup_binlog_formats", ["mixed","row"]], + ["include/have_binlog_format_mixed_or_statement.inc", + "sup_binlog_formats", ["mixed","statement"]], + ["include/have_binlog_format_row_or_statement.inc", + "sup_binlog_formats", ["row","statement"]], ["include/big_test.inc", "big_test", 1], ["include/have_debug.inc", "need_debug", 1], ["include/have_ndb.inc", "ndb_test", 1], @@ -922,8 +920,29 @@ sub mtr_options_from_test_file($$) { mtr_options_from_test_file($tinfo, $sourced_file); } } + } +} + + +sub print_testcases { + my (@cases)= @_; + print "=" x 60, "\n"; + foreach my $test (@cases){ + print "[", $test->{name}, "]", "\n"; + while ((my ($key, $value)) = each(%$test)) { + print " ", $key, "="; + if (ref $value eq "ARRAY") { + print join(", ", @$value); + } else { + print $value; + } + print "\n"; + } + print "\n"; } + print "=" x 60, "\n"; } + 1; diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 7cd6c1362b3..90e72a2cb94 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -50,9 +50,13 @@ my $tot_real_time= 0; sub mtr_report_test_name ($) { my $tinfo= shift; + my $tname= $tinfo->{name}; - _mtr_log("$tinfo->{name}"); - printf "%-30s ", $tinfo->{'name'}; + $tname.= " '$tinfo->{combination}'" + if defined $tinfo->{combination}; + + _mtr_log($tname); + printf "%-30s ", $tname; } sub mtr_report_test_skipped ($) { |