summaryrefslogtreecommitdiff
path: root/mysql-test/lib/mtr_cases.pm
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/lib/mtr_cases.pm')
-rw-r--r--mysql-test/lib/mtr_cases.pm201
1 files changed, 128 insertions, 73 deletions
diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm
index 30310e4448d..5606561d87e 100644
--- a/mysql-test/lib/mtr_cases.pm
+++ b/mysql-test/lib/mtr_cases.pm
@@ -89,6 +89,21 @@ sub init_pattern {
}
+sub testcase_sort_order {
+ my ($a, $b, $sort_criteria)= @_;
+ # Run slow tests first, trying to avoid getting stuck at the end
+ # with a slow test in one worker and the other workers idle.
+ return -1 if $a->{'long_test'} && !$b->{'long_test'};
+ return 1 if !$a->{'long_test'} && $b->{'long_test'};
+
+ my $a_sort_criteria= $sort_criteria->{$a->fullname()};
+ my $b_sort_criteria= $sort_criteria->{$b->fullname()};
+ my $res= $a_sort_criteria cmp $b_sort_criteria;
+ return $res if $res;
+
+ return $a->fullname() cmp $b->fullname();
+}
+
##############################################################################
#
# Collect information about test cases to be run
@@ -157,6 +172,8 @@ sub collect_test_cases ($$$$) {
if ( $opt_reorder && !$quick_collect)
{
# Reorder the test cases in an order that will make them faster to run
+ my %sort_criteria;
+
# Make a mapping of test name to a string that represents how that test
# should be sorted among the other tests. Put the most important criterion
# first, then a sub-criterion, then sub-sub-criterion, etc.
@@ -182,9 +199,10 @@ sub collect_test_cases ($$$$) {
push(@criteria, $tinfo->{force_restart} ? "force-restart" : "no-restart");
$tinfo->{criteria}= join(" ", @criteria);
+ $sort_criteria{$tinfo->fullname()} = $tinfo->{criteria};
}
- @$cases = sort {$a->{criteria} cmp $b->{criteria}; } @$cases;
+ @$cases = sort { testcase_sort_order($a, $b, \%sort_criteria) } @$cases;
# For debugging the sort-order
# foreach my $tinfo (@$cases)
@@ -674,6 +692,7 @@ sub process_opts {
}
}
+
##############################################################################
#
# Collect information about a single test case
@@ -846,7 +865,8 @@ sub collect_one_test_case {
if ( -f "$testdir/$tname.slave-mi");
- my @source_files = tags_from_test_file($tinfo,"$testdir/${tname}.test");
+ my ($master_opts, $slave_opts)=
+ tags_from_test_file($tinfo, "$testdir/${tname}.test", $suitedir);
# Get default storage engine from suite.opt file
@@ -868,9 +888,14 @@ sub collect_one_test_case {
if ( $tinfo->{'big_test'} and ! $::opt_big_test )
{
$tinfo->{'skip'}= 1;
- $tinfo->{'comment'}= "Test needs 'big-test' option";
+ $tinfo->{'comment'}= "Test needs --big-test";
return $tinfo
}
+ if ( $tinfo->{'big_test'} )
+ {
+ # All 'big_test' takes a long time to run
+ $tinfo->{'long_test'}= 1;
+ }
if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries )
{
@@ -893,7 +918,7 @@ sub collect_one_test_case {
{
# All ndb test's should be skipped
$tinfo->{'skip'}= 1;
- $tinfo->{'comment'}= "No ndbcluster tests(--skip-ndbcluster)";
+ $tinfo->{'comment'}= "No ndbcluster";
return $tinfo;
}
}
@@ -914,7 +939,7 @@ sub collect_one_test_case {
if ( $skip_rpl )
{
$tinfo->{'skip'}= 1;
- $tinfo->{'comment'}= "No replication tests(--skip-rpl)";
+ $tinfo->{'comment'}= "No replication tests";
return $tinfo;
}
}
@@ -1000,16 +1025,8 @@ sub collect_one_test_case {
# ----------------------------------------------------------------------
# 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);
+ push @{$tinfo->{'master_opt'}}, @$master_opts, @::opt_extra_mysqld_opt;
+ push @{$tinfo->{'slave_opt'}}, @$slave_opts, @::opt_extra_mysqld_opt;
process_opts($tinfo, 'master_opt');
process_opts($tinfo, 'slave_opt');
@@ -1018,76 +1035,114 @@ sub collect_one_test_case {
}
-# List of tags in the .test files that if found should set
-# the specified value in "tinfo"
-my @tags=
-(
- ["include/big_test.inc", "big_test", 1],
- ["include/have_debug.inc", "need_debug", 1],
- ["include/have_ndb.inc", "ndb_test", 1],
- ["include/have_multi_ndb.inc", "ndb_test", 1],
- ["include/master-slave.inc", "rpl_test", 1],
- ["include/ndb_master-slave.inc", "rpl_test", 1],
- ["include/ndb_master-slave.inc", "ndb_test", 1],
- ["include/not_embedded.inc", "not_embedded", 1],
- ["include/not_valgrind.inc", "not_valgrind", 1],
- ["include/have_ssl.inc", "need_ssl", 1],
- ["include/check_ipv6.inc", "need_ipv6", 1],
-);
-
-
-sub tags_from_test_file {
-
- my $tinfo= shift;
- my $file= shift;
-
- return unless -f $file;
-
- #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> )
+my $tags_map= {'big_test' => ['big_test', 1],
+ 'have_debug' => ['need_debug', 1],
+ 'have_ndb' => ['ndb_test', 1],
+ 'have_multi_ndb' => ['ndb_test', 1],
+ 'master-slave' => ['rpl_test', 1],
+ 'ndb_master-slave' => ['rpl_test', 1, 'ndb_test', 1],
+ 'not_embedded' => ['not_embedded', 1],
+ 'not_valgrind' => ['not_valgrind', 1],
+ 'have_ssl' => ['need_ssl', 1],
+ 'include/check_ipv6.inc' => ['need_ipv6', 1],
+ 'long_test' => ['long_test', 1],
+};
+my $tags_regex_string= join('|', keys %$tags_map);
+my $tags_regex= qr:include/($tags_regex_string)\.inc:o;
+
+my $file_to_tags= { };
+my $file_to_master_opts= { };
+my $file_to_slave_opts= { };
+
+# Get various tags from a file, recursively scanning also included files.
+# And get options from .opt file, also recursively for included files.
+# Return a list of [TAG_TO_SET, VALUE_TO_SET_TO] of found tags.
+# Also returns lists of options for master and slave found in .opt files.
+# Each include file is scanned only once, and subsequent calls just look up the
+# cached result.
+# We need to be a bit careful about speed here; previous version of this code
+# took forever to scan the full test suite.
+sub get_tags_from_file {
+ my ($file, $suitedir)= @_;
+
+ return ('', '', '') unless -f $file;
+
+ return ($file_to_tags->{$file}, $file_to_master_opts->{$file},
+ $file_to_slave_opts->{$file})
+ if exists($file_to_tags->{$file});
+
+ my $F= IO::File->new($file)
+ or mtr_error("can't open file \"$file\": $!");
+
+ my $tags= [];
+ my $master_opts= [];
+ my $slave_opts= [];
+
+ while (my $line= <$F>)
{
+ # Ignore comments.
+ next if $line =~ /^\#/;
- # Skip line if it start's with #
- next if ( $line =~ /^#/ );
-
- # Match this line against tag in "tags" array
- foreach my $tag (@tags)
+ # Add any tag we find.
+ if ($line =~ /$tags_regex/o)
{
- if ( index($line, $tag->[0]) >= 0 )
+ my $to_set= $tags_map->{$1};
+ for (my $i= 0; $i < @$to_set; $i+= 2)
{
- # Tag matched, assign value to "tinfo"
- $tinfo->{"$tag->[1]"}= $tag->[2];
+ push @$tags, [$to_set->[$i], $to_set->[$i+1]];
}
}
- # If test sources another file, open it as well
- if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ or
- $line =~ /^([[:space:]]*)source(.*);$/ )
+ # Check for a sourced include file.
+ if ($line =~ /^(--)?[[:space:]]*source[[:space:]]+([^;[:space:]]+)/)
{
- my $value= $2;
- $value =~ s/^\s+//; # Remove leading space
- $value =~ s/[[:space:]]+$//; # Remove ending space
-
- # Sourced file may exist relative to test or
- # in global location
- foreach my $sourced_file (dirname($file). "/$value",
- "$::glob_mysql_test_dir/$value")
+ my $include= $2;
+ # Sourced file may exist relative to test file, or in global location.
+ # Note that for the purpose of tag collection we ignore
+ # non-existing files, and let mysqltest handle the error
+ # (e.g. mysqltest.test needs this)
+ for my $sourced_file (dirname($file) . '/' . $include,
+ $suitedir . '/' . $include,
+ $::glob_mysql_test_dir . '/' . $include)
{
- if ( -f $sourced_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)
- unshift @all_files, tags_from_test_file($tinfo, $sourced_file);
- last;
- }
+ if (-e $sourced_file)
+ {
+ my ($sub_tags, $sub_master_opts, $sub_slave_opts)=
+ get_tags_from_file($sourced_file, $suitedir);
+ push @$tags, @$sub_tags;
+ push @$master_opts, @$sub_master_opts;
+ push @$slave_opts, @$sub_slave_opts;
+ last;
+ }
}
}
}
- @all_files;
+
+ # Add options from main file _after_ those of any includes; this allows a
+ # test file to override options set by includes (eg. rpl.rpl_ddl uses this
+ # to enable innodb, then disable innodb in the slave.
+ my $file_no_ext= $file;
+ $file_no_ext =~ s/\.\w+$//;
+ my @common_opts= opts_from_file("$file_no_ext.opt");
+ push @$master_opts, @common_opts, opts_from_file("$file_no_ext-master.opt");
+ push @$slave_opts, @common_opts, opts_from_file("$file_no_ext-slave.opt");
+
+ # Save results so we can reuse without parsing if seen again.
+ $file_to_tags->{$file}= $tags;
+ $file_to_master_opts->{$file}= $master_opts;
+ $file_to_slave_opts->{$file}= $slave_opts;
+ return ($tags, $master_opts, $slave_opts);
+}
+
+sub tags_from_test_file {
+ my ($tinfo, $file, $suitedir)= @_;
+
+ my ($tags, $master_opts, $slave_opts)= get_tags_from_file($file, $suitedir);
+ for (@$tags)
+ {
+ $tinfo->{$_->[0]}= $_->[1];
+ }
+ return ($master_opts, $slave_opts);
}
sub unspace {