~maria-captains/maria/mariadb-5.1-knielsen

« back to all changes in this revision

Viewing changes to mysql-test/lib/mtr_cases.pm

  • Committer: knielsen at knielsen-hq
  • Date: 2011-07-31 20:25:37 UTC
  • Revision ID: knielsen@knielsen-hq.org-20110731202537-0v8qbzoy9ov2yy0q
Speed up mysql-test-run.pl.

Problem was the parsing of test suite files for various tags and options.
This was done inefficiently, and include files were re-parsed for every
place they were included. This caused a delay of 20 seconds or so before
the first test started to run.

By parsing more efficiently and re-using first parse for subsequent
inclusion of the same file, time spent parsing is reduced to less than
1 second, and start appears instantaneous.

(With this patch, full ./mtr runs in 3 minutes on my laptop (release
build.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
890
890
    if ( -f "$testdir/$tname.slave-mi");
891
891
 
892
892
 
893
 
  my @source_files = tags_from_test_file($tinfo,"$testdir/${tname}.test");
 
893
  my ($master_opts, $slave_opts)=
 
894
    tags_from_test_file($tinfo, "$testdir/${tname}.test", $suitedir);
894
895
 
895
896
  # Get default storage engine from suite.opt file
896
897
 
1043
1044
  # ----------------------------------------------------------------------
1044
1045
  # Append mysqld extra options to master and slave, as appropriate
1045
1046
  # ----------------------------------------------------------------------
1046
 
  for (@source_files) {
1047
 
    s/\.\w+$//;
1048
 
    push @{$tinfo->{master_opt}}, opts_from_file("$_.opt");
1049
 
    push @{$tinfo->{slave_opt}}, opts_from_file("$_.opt");
1050
 
    push @{$tinfo->{master_opt}}, opts_from_file("$_-master.opt");
1051
 
    push @{$tinfo->{slave_opt}}, opts_from_file("$_-slave.opt");
1052
 
  }
1053
 
 
1054
 
  push(@{$tinfo->{'master_opt'}}, @::opt_extra_mysqld_opt);
1055
 
  push(@{$tinfo->{'slave_opt'}}, @::opt_extra_mysqld_opt);
 
1047
  push @{$tinfo->{'master_opt'}}, @$master_opts, @::opt_extra_mysqld_opt;
 
1048
  push @{$tinfo->{'slave_opt'}}, @$slave_opts, @::opt_extra_mysqld_opt;
1056
1049
 
1057
1050
  process_opts($tinfo, 'master_opt');
1058
1051
  process_opts($tinfo, 'slave_opt');
1061
1054
}
1062
1055
 
1063
1056
 
1064
 
# List of tags in the .test files that if found should set
1065
 
# the specified value in "tinfo"
1066
 
my @tags=
1067
 
(
1068
 
 ["include/big_test.inc", "big_test", 1],
1069
 
 ["include/have_debug.inc", "need_debug", 1],
1070
 
 ["include/have_ndb.inc", "ndb_test", 1],
1071
 
 ["include/have_multi_ndb.inc", "ndb_test", 1],
1072
 
 ["include/master-slave.inc", "rpl_test", 1],
1073
 
 ["include/ndb_master-slave.inc", "rpl_test", 1],
1074
 
 ["include/ndb_master-slave.inc", "ndb_test", 1],
1075
 
 ["include/not_embedded.inc", "not_embedded", 1],
1076
 
 ["include/not_valgrind.inc", "not_valgrind", 1],
1077
 
 ["include/have_example_plugin.inc", "example_plugin_test", 1],
1078
 
 ["include/have_ssl.inc", "need_ssl", 1],
1079
 
 ["include/long_test.inc", "long_test", 1],
1080
 
);
1081
 
 
 
1057
my $tags_map= {'big_test' => ['big_test', 1],
 
1058
               'have_debug' => ['need_debug', 1],
 
1059
               'have_ndb' => ['ndb_test', 1],
 
1060
               'have_multi_ndb' => ['ndb_test', 1],
 
1061
               'master-slave' => ['rpl_test', 1],
 
1062
               'ndb_master-slave' => ['rpl_test', 1, 'ndb_test', 1],
 
1063
               'not_embedded' => ['not_embedded', 1],
 
1064
               'not_valgrind' => ['not_valgrind', 1],
 
1065
               'have_example_plugin' => ['example_plugin_test', 1],
 
1066
               'have_oqgraph_engine' => ['oqgraph_test', 1],
 
1067
               'have_ssl' => ['need_ssl', 1],
 
1068
               'long_test' => ['long_test', 1],
 
1069
};
 
1070
my $tags_regex_string= join('|', keys %$tags_map);
 
1071
my $tags_regex= qr:include/($tags_regex_string)\.inc:o;
 
1072
 
 
1073
my $file_to_tags= { };
 
1074
my $file_to_master_opts= { };
 
1075
my $file_to_slave_opts= { };
 
1076
 
 
1077
# Get various tags from a file, recursively scanning also included files.
 
1078
# And get options from .opt file, also recursively for included files.
 
1079
# Return a list of [TAG_TO_SET, VALUE_TO_SET_TO] of found tags.
 
1080
# Also returns lists of options for master and slave found in .opt files.
 
1081
# Each include file is scanned only once, and subsequent calls just look up the
 
1082
# cached result.
 
1083
# We need to be a bit careful about speed here; previous version of this code
 
1084
# took forever to scan the full test suite.
 
1085
sub get_tags_from_file {
 
1086
  my ($file, $suitedir)= @_;
 
1087
 
 
1088
  return ($file_to_tags->{$file}, $file_to_master_opts->{$file},
 
1089
          $file_to_slave_opts->{$file})
 
1090
    if exists($file_to_tags->{$file});
 
1091
 
 
1092
  my $F= IO::File->new($file)
 
1093
    or mtr_error("can't open file \"$file\": $!");
 
1094
 
 
1095
  my $tags= [];
 
1096
  my $master_opts= [];
 
1097
  my $slave_opts= [];
 
1098
 
 
1099
  while (my $line= <$F>)
 
1100
  {
 
1101
    # Ignore comments.
 
1102
    next if $line =~ /^\#/;
 
1103
 
 
1104
    # Add any tag we find.
 
1105
    if ($line =~ /$tags_regex/o)
 
1106
    {
 
1107
      my $to_set= $tags_map->{$1};
 
1108
      for (my $i= 0; $i < @$to_set; $i+= 2)
 
1109
      {
 
1110
        push @$tags, [$to_set->[$i], $to_set->[$i+1]];
 
1111
      }
 
1112
    }
 
1113
 
 
1114
    # Check for a sourced include file.
 
1115
    if ($line =~ /^(--)?[[:space:]]*source[[:space:]]+([^;[:space:]]+)/)
 
1116
    {
 
1117
      my $include= $2;
 
1118
      # Sourced file may exist relative to test file, or in global location.
 
1119
      # Note that for the purpose of tag collection we ignore
 
1120
      # non-existing files, and let mysqltest handle the error
 
1121
      # (e.g. mysqltest.test needs this)
 
1122
      for my $sourced_file (dirname($file) . '/' . $include,
 
1123
                            $suitedir . '/' . $include,
 
1124
                            $::glob_mysql_test_dir . '/' . $include)
 
1125
      {
 
1126
        if (-e $sourced_file)
 
1127
        {
 
1128
          my ($sub_tags, $sub_master_opts, $sub_slave_opts)=
 
1129
            get_tags_from_file($sourced_file, $suitedir);
 
1130
          push @$tags, @$sub_tags;
 
1131
          push @$master_opts, @$sub_master_opts;
 
1132
          push @$slave_opts, @$sub_slave_opts;
 
1133
          last;
 
1134
        }
 
1135
      }
 
1136
    }
 
1137
  }
 
1138
 
 
1139
  # Add options from main file _after_ those of any includes; this allows a
 
1140
  # test file to override options set by includes (eg. rpl.rpl_ddl uses this
 
1141
  # to enable innodb, then disable innodb in the slave.
 
1142
  my $file_no_ext= $file;
 
1143
  $file_no_ext =~ s/\.\w+$//;
 
1144
  my @common_opts= opts_from_file("$file_no_ext.opt");
 
1145
  push @$master_opts, @common_opts, opts_from_file("$file_no_ext-master.opt");
 
1146
  push @$slave_opts, @common_opts, opts_from_file("$file_no_ext-slave.opt");
 
1147
 
 
1148
  # Save results so we can reuse without parsing if seen again.
 
1149
  $file_to_tags->{$file}= $tags;
 
1150
  $file_to_master_opts->{$file}= $master_opts;
 
1151
  $file_to_slave_opts->{$file}= $slave_opts;
 
1152
  return ($tags, $master_opts, $slave_opts);
 
1153
}
1082
1154
 
1083
1155
sub tags_from_test_file {
1084
 
  my $tinfo= shift;
1085
 
  my $file= shift;
1086
 
  #mtr_verbose("$file");
1087
 
  my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!");
1088
 
  my @all_files=($file);
 
1156
  my ($tinfo, $file, $suitedir)= @_;
1089
1157
 
1090
 
  while ( my $line= <$F> )
 
1158
  my ($tags, $master_opts, $slave_opts)= get_tags_from_file($file, $suitedir);
 
1159
  for (@$tags)
1091
1160
  {
1092
 
 
1093
 
    # Skip line if it start's with #
1094
 
    next if ( $line =~ /^#/ );
1095
 
 
1096
 
    # Match this line against tag in "tags" array
1097
 
    foreach my $tag (@tags)
1098
 
    {
1099
 
      if ( index($line, $tag->[0]) >= 0 )
1100
 
      {
1101
 
        # Tag matched, assign value to "tinfo"
1102
 
        $tinfo->{"$tag->[1]"}= $tag->[2];
1103
 
      }
1104
 
    }
1105
 
 
1106
 
    # If test sources another file, open it as well
1107
 
    if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ or
1108
 
         $line =~ /^([[:space:]]*)source(.*);$/ )
1109
 
    {
1110
 
      my $value= $2;
1111
 
      $value =~ s/^\s+//;  # Remove leading space
1112
 
      $value =~ s/[[:space:]]+$//;  # Remove ending space
1113
 
 
1114
 
      # Sourced file may exist relative to test or
1115
 
      # in global location
1116
 
      foreach my $sourced_file (dirname($file). "/$value",
1117
 
                                "$::glob_mysql_test_dir/$value")
1118
 
      {
1119
 
        if ( -f $sourced_file )
1120
 
        {
1121
 
          # Only source the file if it exists, we may get
1122
 
          # false positives in the regexes above if someone
1123
 
          # writes "source nnnn;" in a test case(such as mysqltest.test)
1124
 
          unshift @all_files, tags_from_test_file($tinfo, $sourced_file);
1125
 
          last;
1126
 
        }
1127
 
      }
1128
 
    }
 
1161
    $tinfo->{$_->[0]}= $_->[1];
1129
1162
  }
1130
 
  @all_files;
 
1163
  return ($master_opts, $slave_opts);
1131
1164
}
1132
1165
 
1133
1166
sub unspace {