1# -*- cperl -*-
2# Copyright (c) 2005, 2006 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
3# Use is subject to license terms.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License, version 2.0,
7# as published by the Free Software Foundation.
8#
9# This program is also distributed with certain software (including
10# but not limited to OpenSSL) that is licensed under separate terms,
11# as designated in a particular file or component or in included license
12# documentation.  The authors of MySQL hereby grant you an additional
13# permission to link the program and your derivative works with the
14# separately licensed software that they have included with MySQL.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19# GNU General Public License, version 2.0, for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24
25# This is a library file used by the Perl version of mysql-test-run,
26# and is part of the translation of the Bourne shell script with the
27# same name.
28
29use File::Basename;
30use IO::File();
31use strict;
32
33use My::Config;
34
35sub collect_test_cases ($);
36sub collect_one_suite ($);
37sub collect_one_test_case ($$$$$$$$$);
38
39sub mtr_options_from_test_file($$);
40
41my $do_test;
42my $skip_test;
43my %incompatible;
44
45sub init_pattern {
46  my ($from, $what)= @_;
47  if ( $from =~ /^[a-z0-9]$/ ) {
48    # Does not contain any regex, make the pattern match
49    # beginning of string
50    $from= "^$from";
51  }
52  # Check that pattern is a valid regex
53  eval { "" =~/$from/; 1 } or
54    mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@");
55  return $from;
56}
57
58
59sub collect_incomp_tests {
60  open (INCOMP, "lib/v1/incompatible.tests");
61  while (<INCOMP>)
62  {
63    next unless /^\w/;
64    s/\s.*\n//;		      # Ignore anything from first white space
65    $incompatible{$_}= 1;
66  }
67}
68
69##############################################################################
70#
71#  Collect information about test cases we are to run
72#
73##############################################################################
74
75sub collect_test_cases ($) {
76  $do_test= init_pattern($::opt_do_test, "--do-test");
77  $skip_test= init_pattern($::opt_skip_test, "--skip-test");
78
79  collect_incomp_tests();
80
81  my $suites= shift; # Semicolon separated list of test suites
82  my $cases = [];    # Array of hash
83
84  foreach my $suite (split(",", $suites))
85  {
86    push(@$cases, collect_one_suite($suite));
87  }
88
89
90  if ( @::opt_cases )
91  {
92    # Check that the tests specified was found
93    # in at least one suite
94    foreach my $test_name_spec ( @::opt_cases )
95    {
96      my $found= 0;
97      my ($sname, $tname, $extension)= split_testname($test_name_spec);
98      foreach my $test ( @$cases )
99      {
100	# test->{name} is always in suite.name format
101	if ( $test->{name} =~ /.*\.$tname/ )
102	{
103	  $found= 1;
104	}
105      }
106      if ( not $found )
107      {
108	mtr_error("Could not find $tname in any suite");
109      }
110    }
111  }
112
113  if ( $::opt_reorder )
114  {
115    # Reorder the test cases in an order that will make them faster to run
116    my %sort_criteria;
117
118    # Make a mapping of test name to a string that represents how that test
119    # should be sorted among the other tests.  Put the most important criterion
120    # first, then a sub-criterion, then sub-sub-criterion, et c.
121    foreach my $tinfo (@$cases)
122    {
123      my @criteria = ();
124
125      # Look for tests that muct be in run in a defined order
126      # that is defined by test having the same name except for
127      # the ending digit
128
129      # Put variables into hash
130      my $test_name= $tinfo->{'name'};
131      my $depend_on_test_name;
132      if ( $test_name =~ /^([\D]+)([0-9]{1})$/ )
133      {
134	my $base_name= $1;
135	my $idx= $2;
136	mtr_verbose("$test_name =>  $base_name idx=$idx");
137	if ( $idx > 1 )
138	{
139	  $idx-= 1;
140	  $base_name= "$base_name$idx";
141	  mtr_verbose("New basename $base_name");
142	}
143
144	foreach my $tinfo2 (@$cases)
145	{
146	  if ( $tinfo2->{'name'} eq $base_name )
147	  {
148	    mtr_verbose("found dependent test $tinfo2->{'name'}");
149	    $depend_on_test_name=$base_name;
150	  }
151	}
152      }
153
154      if ( defined $depend_on_test_name )
155      {
156	mtr_verbose("Giving $test_name same critera as $depend_on_test_name");
157	$sort_criteria{$test_name} = $sort_criteria{$depend_on_test_name};
158      }
159      else
160      {
161	#
162	# Append the criteria for sorting, in order of importance.
163	#
164	push(@criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0"));
165	# Group test with equal options together.
166	# Ending with "~" makes empty sort later than filled
167	push(@criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~");
168
169	$sort_criteria{$test_name} = join(" ", @criteria);
170      }
171    }
172
173    @$cases = sort {
174      $sort_criteria{$a->{'name'}} . $a->{'name'} cmp
175	$sort_criteria{$b->{'name'}} . $b->{'name'}; } @$cases;
176
177    if ( $::opt_script_debug )
178    {
179      # For debugging the sort-order
180      foreach my $tinfo (@$cases)
181      {
182	print("$sort_criteria{$tinfo->{'name'}} -> \t$tinfo->{'name'}\n");
183      }
184    }
185  }
186
187  return $cases;
188
189}
190
191# Valid extensions and their corresonding component id
192my %exts = ( 'test' => 'mysqld',
193	     'imtest' => 'im'
194	   );
195
196
197# Returns (suitename, testname, extension)
198sub split_testname {
199  my ($test_name)= @_;
200
201  # Get rid of directory part and split name on .'s
202  my @parts= split(/\./, basename($test_name));
203
204  if (@parts == 1){
205    # Only testname given, ex: alias
206    return (undef , $parts[0], undef);
207  } elsif (@parts == 2) {
208    # Either testname.test or suite.testname given
209    # Ex. main.alias or alias.test
210
211    if (defined $exts{$parts[1]})
212    {
213      return (undef , $parts[0], $parts[1]);
214    }
215    else
216    {
217      return ($parts[0], $parts[1], undef);
218    }
219
220  } elsif (@parts == 3) {
221    # Fully specified suitename.testname.test
222    # ex main.alias.test
223    return ( $parts[0], $parts[1], $parts[2]);
224  }
225
226  mtr_error("Illegal format of test name: $test_name");
227}
228
229
230sub collect_one_suite($)
231{
232  my $suite= shift;  # Test suite name
233  my @cases;  # Array of hash
234
235  mtr_verbose("Collecting: $suite");
236
237  my $suitedir= "$::glob_mysql_test_dir"; # Default
238  if ( $suite ne "main" )
239  {
240    $suitedir= mtr_path_exists("$suitedir/suite/$suite",
241			       "$suitedir/$suite");
242    mtr_verbose("suitedir: $suitedir");
243  }
244
245  my $testdir= "$suitedir/t";
246  my $resdir=  "$suitedir/r";
247
248  # ----------------------------------------------------------------------
249  # Build a hash of disabled testcases for this suite
250  # ----------------------------------------------------------------------
251  my %disabled;
252  if ( open(DISABLED, "$testdir/disabled.def" ) )
253  {
254    while ( <DISABLED> )
255      {
256        chomp;
257        if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
258          {
259            $disabled{$1}= $2;
260          }
261      }
262    close DISABLED;
263  }
264
265  # Read suite.opt file
266  my $suite_opt_file=  "$testdir/suite.opt";
267  my $suite_opts= [];
268  if ( -f $suite_opt_file )
269  {
270    $suite_opts= mtr_get_opts_from_file($suite_opt_file);
271  }
272
273  if ( @::opt_cases )
274  {
275    # Collect in specified order
276    foreach my $test_name_spec ( @::opt_cases )
277    {
278      my ($sname, $tname, $extension)= split_testname($test_name_spec);
279
280      # The test name parts have now been defined
281      #print "  suite_name: $sname\n";
282      #print "  tname:      $tname\n";
283      #print "  extension:  $extension\n";
284
285      # Check cirrect suite if suitename is defined
286      next if (defined $sname and $suite ne $sname);
287
288      my $component_id;
289      if ( defined $extension )
290      {
291	my $full_name= "$testdir/$tname.$extension";
292	# Extension was specified, check if the test exists
293        if ( ! -f $full_name)
294        {
295	  # This is only an error if suite was specified, otherwise it
296	  # could exist in another suite
297          mtr_error("Test '$full_name' was not found in suite '$sname'")
298	    if $sname;
299
300	  next;
301        }
302	$component_id= $exts{$extension};
303      }
304      else
305      {
306	# No extension was specified
307	my ($ext, $component);
308	while (($ext, $component)= each %exts) {
309	  my $full_name= "$testdir/$tname.$ext";
310
311	  if ( ! -f $full_name ) {
312	    next;
313	  }
314	  $component_id= $component;
315	  $extension= $ext;
316	}
317	# Test not found here, could exist in other suite
318	next unless $component_id;
319      }
320
321      collect_one_test_case($testdir,$resdir,$suite,$tname,
322                            "$tname.$extension",\@cases,\%disabled,
323			    $component_id,$suite_opts);
324    }
325  }
326  else
327  {
328    opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");
329
330    foreach my $elem ( sort readdir(TESTDIR) )
331    {
332      my $component_id= undef;
333      my $tname= undef;
334
335      if ($tname= mtr_match_extension($elem, 'test'))
336      {
337        $component_id = 'mysqld';
338      }
339      elsif ($tname= mtr_match_extension($elem, 'imtest'))
340      {
341        $component_id = 'im';
342      }
343      else
344      {
345        next;
346      }
347
348      # Skip tests that does not match the --do-test= filter
349      next if ($do_test and not $tname =~ /$do_test/o);
350
351      collect_one_test_case($testdir,$resdir,$suite,$tname,
352                            $elem,\@cases,\%disabled,$component_id,
353			    $suite_opts);
354    }
355    closedir TESTDIR;
356  }
357
358
359  #  Return empty list if no testcases found
360  return if (@cases == 0);
361
362  # ----------------------------------------------------------------------
363  # Read combinations for this suite and build testcases x combinations
364  # if any combinations exists
365  # ----------------------------------------------------------------------
366  if ( ! $::opt_skip_combination )
367  {
368    my @combinations;
369    my $combination_file= "$suitedir/combinations";
370    #print "combination_file: $combination_file\n";
371    if (@::opt_combinations)
372    {
373      # take the combination from command-line
374      mtr_verbose("Take the combination from command line");
375      foreach my $combination (@::opt_combinations) {
376	my $comb= {};
377	$comb->{name}= $combination;
378	push(@{$comb->{comb_opt}}, $combination);
379	push(@combinations, $comb);
380      }
381    }
382    elsif (-f $combination_file )
383    {
384      # Read combinations file in my.cnf format
385      mtr_verbose("Read combinations file");
386      my $config= My::Config->new($combination_file);
387
388      foreach my $group ($config->groups()) {
389	my $comb= {};
390	$comb->{name}= $group->name();
391        foreach my $option ( $group->options() ) {
392	  push(@{$comb->{comb_opt}}, "--".$option->name()."=".$option->value());
393	}
394	push(@combinations, $comb);
395      }
396    }
397
398    if (@combinations)
399    {
400      print " - adding combinations\n";
401      #print_testcases(@cases);
402
403      my @new_cases;
404      foreach my $comb (@combinations)
405      {
406	foreach my $test (@cases)
407	{
408	  #print $test->{name}, " ", $comb, "\n";
409	  my $new_test= {};
410
411	  while (my ($key, $value) = each(%$test)) {
412	    if (ref $value eq "ARRAY") {
413	      push(@{$new_test->{$key}}, @$value);
414	    } else {
415	      $new_test->{$key}= $value;
416	    }
417	  }
418
419	  # Append the combination options to master_opt and slave_opt
420	  push(@{$new_test->{master_opt}}, @{$comb->{comb_opt}});
421	  push(@{$new_test->{slave_opt}}, @{$comb->{comb_opt}});
422
423	  # Add combination name shrt name
424	  $new_test->{combination}= $comb->{name};
425
426	  # Add the new test to new test cases list
427	  push(@new_cases, $new_test);
428	}
429      }
430      #print_testcases(@new_cases);
431      @cases= @new_cases;
432      #print_testcases(@cases);
433    }
434  }
435
436  optimize_cases(\@cases);
437  #print_testcases(@cases);
438
439  return @cases;
440}
441
442
443#
444# Loop through all test cases
445# - optimize which test to run by skipping unnecessary ones
446# - update settings if necessary
447#
448sub optimize_cases {
449  my ($cases)= @_;
450
451  foreach my $tinfo ( @$cases )
452  {
453    # Skip processing if already marked as skipped
454    next if $tinfo->{skip};
455
456    # =======================================================
457    # If a special binlog format was selected with
458    # --mysqld=--binlog-format=x, skip all test that does not
459    # support it
460    # =======================================================
461    #print "used_binlog_format: $::used_binlog_format\n";
462    if (defined $::used_binlog_format )
463    {
464      # =======================================================
465      # Fixed --binlog-format=x specified on command line
466      # =======================================================
467      if ( defined $tinfo->{'binlog_formats'} )
468      {
469	#print "binlog_formats: ". join(", ", @{$tinfo->{binlog_formats}})."\n";
470
471	# The test supports different binlog formats
472	# check if the selected one is ok
473	my $supported=
474	  grep { $_ eq $::used_binlog_format } @{$tinfo->{'binlog_formats'}};
475	if ( !$supported )
476	{
477	  $tinfo->{'skip'}= 1;
478	  $tinfo->{'comment'}=
479	    "Doesn't support --binlog-format='$::used_binlog_format'";
480	}
481      }
482    }
483    else
484    {
485      # =======================================================
486      # Use dynamic switching of binlog format
487      # =======================================================
488
489      # Get binlog-format used by this test from master_opt
490      my $test_binlog_format;
491      foreach my $opt ( @{$tinfo->{master_opt}} ) {
492	$test_binlog_format=
493	  mtr_match_prefix($opt, "--binlog-format=") || $test_binlog_format;
494      }
495
496      if (defined $test_binlog_format and
497	  defined $tinfo->{binlog_formats} )
498      {
499	my $supported=
500	  grep { $_ eq $test_binlog_format } @{$tinfo->{'binlog_formats'}};
501	if ( !$supported )
502	{
503	  $tinfo->{'skip'}= 1;
504	  $tinfo->{'comment'}=
505	    "Doesn't support --binlog-format='$test_binlog_format'";
506	  next;
507	}
508      }
509    }
510
511  }
512}
513
514
515##############################################################################
516#
517#  Collect information about a single test case
518#
519##############################################################################
520
521
522sub collect_one_test_case($$$$$$$$$) {
523  my $testdir= shift;
524  my $resdir=  shift;
525  my $suite=   shift;
526  my $tname=   shift;
527  my $elem=    shift;
528  my $cases=   shift;
529  my $disabled=shift;
530  my $component_id= shift;
531  my $suite_opts= shift;
532
533  my $path= "$testdir/$elem";
534
535  # ----------------------------------------------------------------------
536  # Skip some tests silently
537  # ----------------------------------------------------------------------
538
539  if ( $::opt_start_from and $tname lt $::opt_start_from )
540  {
541    return;
542  }
543
544
545  my $tinfo= {};
546  $tinfo->{'name'}= basename($suite) . ".$tname";
547  $tinfo->{'result_file'}= "$resdir/$tname.result";
548  $tinfo->{'component_id'} = $component_id;
549  push(@$cases, $tinfo);
550
551  # Remove "combinations" part of test name
552  my $test_base_name= $tinfo->{'name'};
553  $test_base_name=~ s/\s.*\n//;
554
555  if (exists ($incompatible{$test_base_name}))
556  {
557    $tinfo->{'skip'}= 1;
558    $tinfo->{'comment'}= "Test cannot run in mtr v1";
559    return;
560  }
561
562  # ----------------------------------------------------------------------
563  # Skip some tests but include in list, just mark them to skip
564  # ----------------------------------------------------------------------
565
566  if ( $skip_test and $tname =~ /$skip_test/o )
567  {
568    $tinfo->{'skip'}= 1;
569    return;
570  }
571
572  # ----------------------------------------------------------------------
573  # Collect information about test case
574  # ----------------------------------------------------------------------
575
576  $tinfo->{'path'}= $path;
577  $tinfo->{'timezone'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work
578
579  $tinfo->{'slave_num'}= 0; # Default, no slave
580  $tinfo->{'master_num'}= 1; # Default, 1 master
581  if ( defined mtr_match_prefix($tname,"rpl") )
582  {
583    if ( $::opt_skip_rpl )
584    {
585      $tinfo->{'skip'}= 1;
586      $tinfo->{'comment'}= "No replication tests(--skip-rpl)";
587      return;
588    }
589
590    $tinfo->{'slave_num'}= 1; # Default for rpl* tests, use one slave
591
592  }
593
594  if ( defined mtr_match_prefix($tname,"federated") )
595  {
596    # Default, federated uses the first slave as it's federated database
597    $tinfo->{'slave_num'}= 1;
598  }
599
600  my $master_opt_file= "$testdir/$tname-master.opt";
601  my $slave_opt_file=  "$testdir/$tname-slave.opt";
602  my $slave_mi_file=   "$testdir/$tname.slave-mi";
603  my $master_sh=       "$testdir/$tname-master.sh";
604  my $slave_sh=        "$testdir/$tname-slave.sh";
605  my $disabled_file=   "$testdir/$tname.disabled";
606  my $im_opt_file=     "$testdir/$tname-im.opt";
607
608  $tinfo->{'master_opt'}= [];
609  $tinfo->{'slave_opt'}=  [];
610  $tinfo->{'slave_mi'}=   [];
611
612
613  # Add suite opts
614  foreach my $opt ( @$suite_opts )
615  {
616    mtr_verbose($opt);
617    push(@{$tinfo->{'master_opt'}}, $opt);
618    push(@{$tinfo->{'slave_opt'}}, $opt);
619  }
620
621  # Add master opts
622  if ( -f $master_opt_file )
623  {
624
625    my $master_opt= mtr_get_opts_from_file($master_opt_file);
626
627    foreach my $opt ( @$master_opt )
628    {
629      my $value;
630
631      # The opt file is used both to send special options to the mysqld
632      # as well as pass special test case specific options to this
633      # script
634
635      $value= mtr_match_prefix($opt, "--timezone=");
636      if ( defined $value )
637      {
638	$tinfo->{'timezone'}= $value;
639	next;
640      }
641
642      $value= mtr_match_prefix($opt, "--slave-num=");
643      if ( defined $value )
644      {
645	$tinfo->{'slave_num'}= $value;
646	next;
647      }
648
649      $value= mtr_match_prefix($opt, "--result-file=");
650      if ( defined $value )
651      {
652	# Specifies the file mysqltest should compare
653	# output against
654	$tinfo->{'result_file'}= "r/$value.result";
655	next;
656      }
657
658      # If we set default time zone, remove the one we have
659      $value= mtr_match_prefix($opt, "--default-time-zone=");
660      if ( defined $value )
661      {
662	# Set timezone for this test case to something different
663	$tinfo->{'timezone'}= "GMT-8";
664	# Fallthrough, add the --default-time-zone option
665      }
666
667      # The --restart option forces a restart even if no special
668      # option is set. If the options are the same as next testcase
669      # there is no need to restart after the testcase
670      # has completed
671      if ( $opt eq "--force-restart" )
672      {
673	$tinfo->{'force_restart'}= 1;
674	next;
675      }
676
677      # Ok, this was a real option, add it
678      push(@{$tinfo->{'master_opt'}}, $opt);
679    }
680  }
681
682  # Add slave opts
683  if ( -f $slave_opt_file )
684  {
685    my $slave_opt= mtr_get_opts_from_file($slave_opt_file);
686
687    foreach my $opt ( @$slave_opt )
688    {
689      # If we set default time zone, remove the one we have
690      my $value= mtr_match_prefix($opt, "--default-time-zone=");
691      $tinfo->{'slave_opt'}= [] if defined $value;
692    }
693    push(@{$tinfo->{'slave_opt'}}, @$slave_opt);
694  }
695
696  if ( -f $slave_mi_file )
697  {
698    $tinfo->{'slave_mi'}= mtr_get_opts_from_file($slave_mi_file);
699  }
700
701  if ( -f $master_sh )
702  {
703    if ( $::glob_win32_perl )
704    {
705      $tinfo->{'skip'}= 1;
706      $tinfo->{'comment'}= "No tests with sh scripts on Windows";
707      return;
708    }
709    else
710    {
711      $tinfo->{'master_sh'}= $master_sh;
712    }
713  }
714
715  if ( -f $slave_sh )
716  {
717    if ( $::glob_win32_perl )
718    {
719      $tinfo->{'skip'}= 1;
720      $tinfo->{'comment'}= "No tests with sh scripts on Windows";
721      return;
722    }
723    else
724    {
725      $tinfo->{'slave_sh'}= $slave_sh;
726    }
727  }
728
729  if ( -f $im_opt_file )
730  {
731    $tinfo->{'im_opts'} = mtr_get_opts_from_file($im_opt_file);
732  }
733  else
734  {
735    $tinfo->{'im_opts'} = [];
736  }
737
738  # FIXME why this late?
739  my $marked_as_disabled= 0;
740  if ( $disabled->{$tname} )
741  {
742    $marked_as_disabled= 1;
743    $tinfo->{'comment'}= $disabled->{$tname};
744  }
745
746  if ( -f $disabled_file )
747  {
748    $marked_as_disabled= 1;
749    $tinfo->{'comment'}= mtr_fromfile($disabled_file);
750  }
751
752  # If test was marked as disabled, either opt_enable_disabled is off and then
753  # we skip this test, or it is on and then we run this test but warn
754
755  if ( $marked_as_disabled )
756  {
757    if ( $::opt_enable_disabled )
758    {
759      $tinfo->{'dont_skip_though_disabled'}= 1;
760    }
761    else
762    {
763      $tinfo->{'skip'}= 1;
764      $tinfo->{'disable'}= 1;   # Sub type of 'skip'
765      return;
766    }
767  }
768
769  if ( $component_id eq 'im' )
770  {
771    if ( $::glob_use_embedded_server )
772    {
773      $tinfo->{'skip'}= 1;
774      $tinfo->{'comment'}= "No IM with embedded server";
775      return;
776    }
777    elsif ( $::opt_ps_protocol )
778    {
779      $tinfo->{'skip'}= 1;
780      $tinfo->{'comment'}= "No IM with --ps-protocol";
781      return;
782    }
783    elsif ( $::opt_skip_im )
784    {
785      $tinfo->{'skip'}= 1;
786      $tinfo->{'comment'}= "No IM tests(--skip-im)";
787      return;
788    }
789  }
790  else
791  {
792    mtr_options_from_test_file($tinfo,"$testdir/${tname}.test");
793
794    if ( defined $::used_default_engine )
795    {
796      # Different default engine is used
797      # tag test to require that engine
798      $tinfo->{'ndb_test'}= 1
799	if ( $::used_default_engine =~ /^ndb/i );
800
801      $tinfo->{'innodb_test'}= 1
802	if ( $::used_default_engine =~ /^innodb/i );
803    }
804
805    #enable federated for this test
806    if ($tinfo->{'federated_test'})
807    {
808      push(@{$tinfo->{'master_opt'}}, "--loose-federated");
809      push(@{$tinfo->{'slave_opt'}}, "--loose-federated");
810    }
811
812    if ( $tinfo->{'big_test'} and ! $::opt_big_test )
813    {
814      $tinfo->{'skip'}= 1;
815      $tinfo->{'comment'}= "Test need 'big-test' option";
816      return;
817    }
818
819    if ( $tinfo->{'ndb_extra'} and ! $::opt_ndb_extra_test )
820    {
821      $tinfo->{'skip'}= 1;
822      $tinfo->{'comment'}= "Test need 'ndb_extra' option";
823      return;
824    }
825
826    if ( $tinfo->{'require_manager'} )
827    {
828      $tinfo->{'skip'}= 1;
829      $tinfo->{'comment'}= "Test need the _old_ manager(to be removed)";
830      return;
831    }
832
833    if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries )
834    {
835      $tinfo->{'skip'}= 1;
836      $tinfo->{'comment'}= "Test need debug binaries";
837      return;
838    }
839
840    if ( $tinfo->{'ndb_test'} )
841    {
842      # This is a NDB test
843      if ( ! $::glob_ndbcluster_supported )
844      {
845	# Ndb is not supported, skip it
846	$tinfo->{'skip'}= 1;
847	$tinfo->{'comment'}= "No ndbcluster support";
848	return;
849      }
850      elsif ( $::opt_skip_ndbcluster )
851      {
852	# All ndb test's should be skipped
853	$tinfo->{'skip'}= 1;
854	$tinfo->{'comment'}= "No ndbcluster tests(--skip-ndbcluster)";
855	return;
856      }
857      # Ndb tests run with two mysqld masters
858      $tinfo->{'master_num'}= 2;
859    }
860    else
861    {
862      # This is not a ndb test
863      if ( $::opt_with_ndbcluster_only )
864      {
865	# Only the ndb test should be run, all other should be skipped
866	$tinfo->{'skip'}= 1;
867	$tinfo->{'comment'}= "Only ndbcluster tests(--with-ndbcluster-only)";
868	return;
869      }
870    }
871
872    if ( $tinfo->{'innodb_test'} )
873    {
874      # This is a test that need innodb
875      if ( $::mysqld_variables{'innodb'} eq "OFF" )
876      {
877	# innodb is not supported, skip it
878	$tinfo->{'skip'}= 1;
879	$tinfo->{'comment'}= "No innodb support";
880	return;
881      }
882    }
883
884    if ( $tinfo->{'need_binlog'} )
885    {
886      if (grep(/^--skip-log-bin/,  @::opt_extra_mysqld_opt) )
887      {
888	$tinfo->{'skip'}= 1;
889	$tinfo->{'comment'}= "Test need binlog";
890	return;
891      }
892    }
893    else
894    {
895      if ( $::mysql_version_id >= 50100 )
896      {
897	# Test does not need binlog, add --skip-binlog to
898	# the options used when starting it
899	push(@{$tinfo->{'master_opt'}}, "--skip-log-bin");
900      }
901    }
902
903  }
904}
905
906
907# List of tags in the .test files that if found should set
908# the specified value in "tinfo"
909our @tags=
910(
911
912 ["include/have_binlog_format_row.inc", "binlog_formats", ["row"]],
913 ["include/have_binlog_format_statement.inc", "binlog_formats", ["statement"]],
914 ["include/have_binlog_format_mixed.inc", "binlog_formats", ["mixed"]],
915 ["include/have_binlog_format_mixed_or_row.inc",
916  "binlog_formats", ["mixed", "row"]],
917 ["include/have_binlog_format_mixed_or_statement.inc",
918  "binlog_formats", ["mixed", "statement"]],
919 ["include/have_binlog_format_row_or_statement.inc",
920  "binlog_formats", ["row", "statement"]],
921
922 ["include/have_innodb.inc", "innodb_test", 1],
923 ["include/have_log_bin.inc", "need_binlog", 1],
924 ["include/big_test.inc", "big_test", 1],
925 ["include/have_debug.inc", "need_debug", 1],
926 ["include/have_ndb.inc", "ndb_test", 1],
927 ["include/have_multi_ndb.inc", "ndb_test", 1],
928 ["include/have_ndb_extra.inc", "ndb_extra", 1],
929 ["include/ndb_master-slave.inc", "ndb_test", 1],
930 ["require_manager", "require_manager", 1],
931 ["include/federated.inc", "federated_test", 1],
932 ["include/have_federated_db.inc", "federated_test", 1],
933);
934
935sub mtr_options_from_test_file($$) {
936  my $tinfo= shift;
937  my $file= shift;
938  #mtr_verbose("$file");
939  my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!");
940
941  while ( my $line= <$F> )
942  {
943
944    # Skip line if it start's with #
945    next if ( $line =~ /^#/ );
946
947    # Match this line against tag in "tags" array
948    foreach my $tag (@tags)
949    {
950      if ( index($line, $tag->[0]) >= 0 )
951      {
952    	  # Tag matched, assign value to "tinfo"
953        $tinfo->{"$tag->[1]"}= $tag->[2];
954      }
955    }
956
957    # If test sources another file, open it as well
958    if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ or
959	 $line =~ /^([[:space:]]*)source(.*);$/ )
960    {
961      my $value= $2;
962      $value =~ s/^\s+//;  # Remove leading space
963      $value =~ s/[[:space:]]+$//;  # Remove ending space
964
965      my $sourced_file= "$::glob_mysql_test_dir/$value";
966      if ( -f $sourced_file )
967      {
968	# Only source the file if it exists, we may get
969	# false positives in the regexes above if someone
970	# writes "source nnnn;" in a test case(such as mysqltest.test)
971	mtr_options_from_test_file($tinfo, $sourced_file);
972      }
973    }
974  }
975}
976
977
978sub print_testcases {
979  my (@cases)= @_;
980
981  print "=" x 60, "\n";
982  foreach my $test (@cases){
983    print "[", $test->{name}, "]", "\n";
984    while ((my ($key, $value)) = each(%$test)) {
985      print " ", $key, "=";
986      if (ref $value eq "ARRAY") {
987	print join(", ", @$value);
988      } else {
989	print $value;
990      }
991      print "\n";
992    }
993    print "\n";
994  }
995  print "=" x 60, "\n";
996}
997
998
9991;
1000