mtr_cases.pl 14 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6
# -*- cperl -*-

# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.

unknown's avatar
unknown committed
7
use File::Basename;
8
use IO::File();
unknown's avatar
unknown committed
9 10 11
use strict;

sub collect_test_cases ($);
12
sub collect_one_test_case ($$$$$$$);
unknown's avatar
unknown committed
13

unknown's avatar
unknown committed
14 15
sub mtr_options_from_test_file($$);

unknown's avatar
unknown committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
##############################################################################
#
#  Collect information about test cases we are to run
#
##############################################################################

sub collect_test_cases ($) {
  my $suite= shift;             # Test suite name

  my $testdir;
  my $resdir;

  if ( $suite eq "main" )
  {
    $testdir= "$::glob_mysql_test_dir/t";
    $resdir=  "$::glob_mysql_test_dir/r";
  }
  else
  {
    $testdir= "$::glob_mysql_test_dir/suite/$suite/t";
    $resdir=  "$::glob_mysql_test_dir/suite/$suite/r";
  }

  my $cases = [];           # Array of hash, will be array of C struct

  opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
  # ----------------------------------------------------------------------
  # Disable some tests listed in disabled.def
  # ----------------------------------------------------------------------
  my %disabled;
  if ( open(DISABLED, "$testdir/disabled.def" ) )
  {
    while ( <DISABLED> )
      {
        chomp;
        if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
          {
            $disabled{$1}= $2;
          }
      }
    close DISABLED;
  }

unknown's avatar
unknown committed
60 61 62
  if ( @::opt_cases )
  {
    foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
      my $elem= undef;
      my $component_id= undef;
      
      # Get rid of directory part (path). Leave the extension since it is used
      # to understand type of the test.

      $tname = basename($tname);

      # Check if the extenstion has been specified.

      if ( mtr_match_extension($tname, "test") )
      {
        $elem= $tname;
        $tname=~ s/\.test$//;
        $component_id= 'mysqld';
      }
      elsif ( mtr_match_extension($tname, "imtest") )
      {
        $elem= $tname;
        $tname =~ s/\.imtest$//;
        $component_id= 'im';
      }

      # If target component is known, check that the specified test case
      # exists.
      # 
      # Otherwise, try to guess the target component.

unknown's avatar
unknown committed
91
      if ( $component_id )
unknown's avatar
unknown committed
92
      {
93 94 95 96
        if ( ! -f "$testdir/$elem")
        {
          mtr_error("Test case $tname ($testdir/$elem) is not found");
        }
unknown's avatar
unknown committed
97
      }
98 99 100 101 102
      else
      {
        my $mysqld_test_exists = -f "$testdir/$tname.test";
        my $im_test_exists = -f "$testdir/$tname.imtest";

unknown's avatar
unknown committed
103
        if ( $mysqld_test_exists and $im_test_exists )
104 105 106
        {
          mtr_error("Ambiguos test case name ($tname)");
        }
unknown's avatar
unknown committed
107
        elsif ( ! $mysqld_test_exists and ! $im_test_exists )
108 109 110 111 112 113 114 115 116 117 118 119 120 121
        {
          mtr_error("Test case $tname is not found");
        }
        elsif ( $mysqld_test_exists )
        {
          $elem= "$tname.test";
          $component_id= 'mysqld';
        }
        elsif ( $im_test_exists )
        {
          $elem= "$tname.imtest";
          $component_id= 'im';
        }
      }
122

123
      collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
124
        $component_id);
unknown's avatar
unknown committed
125 126 127 128 129 130
    }
    closedir TESTDIR;
  }
  else
  {
    foreach my $elem ( sort readdir(TESTDIR) ) {
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
      my $component_id= undef;
      my $tname= undef;

      if ($tname= mtr_match_extension($elem, 'test'))
      {
        $component_id = 'mysqld';
      }
      elsif ($tname= mtr_match_extension($elem, 'imtest'))
      {
        $component_id = 'im';
      }
      else
      {
        next;
      }
      
unknown's avatar
unknown committed
147 148
      next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test);

149 150
      collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
        $component_id);
unknown's avatar
unknown committed
151 152 153 154 155 156 157
    }
    closedir TESTDIR;
  }

  # To speed things up, we sort first in if the test require a restart
  # or not, second in alphanumeric order.

unknown's avatar
unknown committed
158 159 160
  if ( $::opt_reorder )
  {
    @$cases = sort {
unknown's avatar
unknown committed
161
      if ( ! $a->{'master_restart'} and ! $b->{'master_restart'} )
unknown's avatar
unknown committed
162 163 164
      {
        return $a->{'name'} cmp $b->{'name'};
      }
unknown's avatar
unknown committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178

      if ( $a->{'master_restart'} and $b->{'master_restart'} )
      {
        my $cmp= mtr_cmp_opts($a->{'master_opt'}, $b->{'master_opt'});
        if ( $cmp == 0 )
        {
          return $a->{'name'} cmp $b->{'name'};
        }
        else
        {
          return $cmp;
        }
      }

unknown's avatar
unknown committed
179 180 181 182 183 184 185 186 187 188
      if ( $a->{'master_restart'} )
      {
        return 1;                 # Is greater
      }
      else
      {
        return -1;                # Is less
      }
    } @$cases;
  }
unknown's avatar
unknown committed
189 190 191 192 193 194 195 196 197 198 199 200

  return $cases;
}


##############################################################################
#
#  Collect information about a single test case
#
##############################################################################


201
sub collect_one_test_case($$$$$$$) {
unknown's avatar
unknown committed
202 203 204 205 206
  my $testdir= shift;
  my $resdir=  shift;
  my $tname=   shift;
  my $elem=    shift;
  my $cases=   shift;
unknown's avatar
unknown committed
207
  my $disabled=shift;
208
  my $component_id= shift;
unknown's avatar
unknown committed
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

  my $path= "$testdir/$elem";

  # ----------------------------------------------------------------------
  # Skip some tests silently
  # ----------------------------------------------------------------------

  if ( $::opt_start_from and $tname lt $::opt_start_from )
  {
    return;
  }

  # ----------------------------------------------------------------------
  # Skip some tests but include in list, just mark them to skip
  # ----------------------------------------------------------------------

  my $tinfo= {};
  $tinfo->{'name'}= $tname;
  $tinfo->{'result_file'}= "$resdir/$tname.result";
228
  $tinfo->{'component_id'} = $component_id;
unknown's avatar
unknown committed
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
  push(@$cases, $tinfo);

  if ( $::opt_skip_test and defined mtr_match_prefix($tname,$::opt_skip_test) )
  {
    $tinfo->{'skip'}= 1;
    return;
  }

  # ----------------------------------------------------------------------
  # Collect information about test case
  # ----------------------------------------------------------------------

  $tinfo->{'path'}= $path;
  $tinfo->{'timezone'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work

  if ( defined mtr_match_prefix($tname,"rpl") )
  {
    if ( $::opt_skip_rpl )
    {
      $tinfo->{'skip'}= 1;
249
      $tinfo->{'comment'}= "No replication tests(--skip-rpl)";
unknown's avatar
unknown committed
250 251 252 253 254 255 256
      return;
    }

    $tinfo->{'slave_num'}= 1;           # Default, use one slave

    if ( $tname eq 'rpl_failsafe' or $tname eq 'rpl_chain_temp_table' )
    {
257
      # $tinfo->{'slave_num'}= 3;         # Not 3 ? Check old code, strange
unknown's avatar
unknown committed
258 259 260
    }
  }

unknown's avatar
unknown committed
261 262
  if ( defined mtr_match_prefix($tname,"federated") )
  {
263 264
    # Default, federated uses the first slave as it's federated database
    $tinfo->{'slave_num'}= 1;
unknown's avatar
unknown committed
265 266
  }

unknown's avatar
unknown committed
267
  if ( $::opt_with_ndbcluster or defined mtr_match_substring($tname,"ndb") )
268
  {
269
    # This is an ndb test or all tests should be run with ndb cluster started
270
    $tinfo->{'ndb_test'}= 1;
271 272
    if ( $::opt_skip_ndbcluster )
    {
273
      # All ndb test's should be skipped
274
      $tinfo->{'skip'}= 1;
275
      $tinfo->{'comment'}= "No ndbcluster test(--skip-ndbcluster)";
276 277
      return;
    }
unknown's avatar
unknown committed
278
    if ( ! $::opt_ndbcluster_supported )
279 280
    {
      # Ndb is not supported, skip them
281
      $tinfo->{'skip'}= 1;
282
      $tinfo->{'comment'}= "No ndbcluster support";
283 284
      return;
    }
285 286 287
  }
  else
  {
288
    # This is not a ndb test
289
    $tinfo->{'ndb_test'}= 0;
290
    if ( $::opt_with_ndbcluster_only )
unknown's avatar
unknown committed
291
    {
292
      # Only the ndb test should be run, all other should be skipped
293
      $tinfo->{'skip'}= 1;
unknown's avatar
unknown committed
294
      $tinfo->{'comment'}= "Only ndbcluster tests(--with-ndbcluster-only)";
295 296
      return;
    }
297 298
  }

unknown's avatar
unknown committed
299 300 301 302 303 304 305
  # FIXME what about embedded_server + ndbcluster, skip ?!

  my $master_opt_file= "$testdir/$tname-master.opt";
  my $slave_opt_file=  "$testdir/$tname-slave.opt";
  my $slave_mi_file=   "$testdir/$tname.slave-mi";
  my $master_sh=       "$testdir/$tname-master.sh";
  my $slave_sh=        "$testdir/$tname-slave.sh";
unknown's avatar
unknown committed
306
  my $disabled_file=   "$testdir/$tname.disabled";
307
  my $im_opt_file=     "$testdir/$tname-im.opt";
unknown's avatar
unknown committed
308

unknown's avatar
unknown committed
309 310
  $tinfo->{'master_opt'}= [];
  $tinfo->{'slave_opt'}=  [];
unknown's avatar
unknown committed
311 312 313 314 315 316
  $tinfo->{'slave_mi'}=   [];

  if ( -f $master_opt_file )
  {
    $tinfo->{'master_restart'}= 1;    # We think so for now

unknown's avatar
unknown committed
317
  MASTER_OPT:
unknown's avatar
unknown committed
318
    {
unknown's avatar
unknown committed
319
      my $master_opt= mtr_get_opts_from_file($master_opt_file);
unknown's avatar
unknown committed
320

unknown's avatar
unknown committed
321
      foreach my $opt ( @$master_opt )
unknown's avatar
unknown committed
322
      {
unknown's avatar
unknown committed
323
        my $value;
unknown's avatar
unknown committed
324

unknown's avatar
unknown committed
325 326 327
        # This is a dirty hack from old mysql-test-run, we use the opt
        # file to flag other things as well, it is not a opt list at
        # all
unknown's avatar
unknown committed
328

unknown's avatar
unknown committed
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
        $value= mtr_match_prefix($opt, "--timezone=");
        if ( defined $value )
        {
          $tinfo->{'timezone'}= $value;
          last MASTER_OPT;
        }

        $value= mtr_match_prefix($opt, "--result-file=");
        if ( defined $value )
        {
          $tinfo->{'result_file'}= "r/$value.result";
          if ( $::opt_result_ext and $::opt_record or
               -f "$tinfo->{'result_file'}$::opt_result_ext")
          {
            $tinfo->{'result_file'}.= $::opt_result_ext;
          }
          $tinfo->{'master_restart'}= 0;
          last MASTER_OPT;
        }

        # If we set default time zone, remove the one we have
        $value= mtr_match_prefix($opt, "--default-time-zone=");
        if ( defined $value )
unknown's avatar
unknown committed
352
        {
unknown's avatar
unknown committed
353
          $tinfo->{'master_opt'}= [];
unknown's avatar
unknown committed
354
        }
unknown's avatar
unknown committed
355

unknown's avatar
unknown committed
356
      }
unknown's avatar
unknown committed
357 358 359

      # Ok, this was a real option list, add it
      push(@{$tinfo->{'master_opt'}}, @$master_opt);
unknown's avatar
unknown committed
360 361 362 363 364 365
    }
  }

  if ( -f $slave_opt_file )
  {
    $tinfo->{'slave_restart'}= 1;
unknown's avatar
unknown committed
366 367 368 369 370 371 372 373 374
    my $slave_opt= mtr_get_opts_from_file($slave_opt_file);

    foreach my $opt ( @$slave_opt )
    {
      # If we set default time zone, remove the one we have
      my $value= mtr_match_prefix($opt, "--default-time-zone=");
      $tinfo->{'slave_opt'}= [] if defined $value;
    }
    push(@{$tinfo->{'slave_opt'}}, @$slave_opt);
unknown's avatar
unknown committed
375 376 377 378 379 380 381 382 383 384 385 386 387
  }

  if ( -f $slave_mi_file )
  {
    $tinfo->{'slave_mi'}= mtr_get_opts_from_file($slave_mi_file);
    $tinfo->{'slave_restart'}= 1;
  }

  if ( -f $master_sh )
  {
    if ( $::glob_win32_perl )
    {
      $tinfo->{'skip'}= 1;
388
      $tinfo->{'comment'}= "No tests with sh scripts on Windows";
unknown's avatar
unknown committed
389 390 391 392 393 394 395 396 397 398 399 400 401
    }
    else
    {
      $tinfo->{'master_sh'}= $master_sh;
      $tinfo->{'master_restart'}= 1;
    }
  }

  if ( -f $slave_sh )
  {
    if ( $::glob_win32_perl )
    {
      $tinfo->{'skip'}= 1;
402
      $tinfo->{'comment'}= "No tests with sh scripts on Windows";
unknown's avatar
unknown committed
403 404 405 406 407 408 409 410
    }
    else
    {
      $tinfo->{'slave_sh'}= $slave_sh;
      $tinfo->{'slave_restart'}= 1;
    }
  }

411 412 413 414 415 416 417 418 419
  if ( -f $im_opt_file )
  {
    $tinfo->{'im_opts'} = mtr_get_opts_from_file($im_opt_file);
  }
  else
  {
    $tinfo->{'im_opts'} = [];
  }

unknown's avatar
unknown committed
420
  # FIXME why this late?
421
  my $marked_as_disabled= 0;
unknown's avatar
unknown committed
422
  if ( $disabled->{$tname} )
unknown's avatar
unknown committed
423
  {
424 425
    $marked_as_disabled= 1;
    $tinfo->{'comment'}= $disabled->{$tname};
unknown's avatar
unknown committed
426 427
  }

unknown's avatar
unknown committed
428
  if ( -f $disabled_file )
unknown's avatar
unknown committed
429
  {
430
    $marked_as_disabled= 1;
unknown's avatar
unknown committed
431
    $tinfo->{'comment'}= mtr_fromfile($disabled_file);
unknown's avatar
unknown committed
432 433
  }

434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
  # If test was marked as disabled, either opt_enable_disabled is off and then
  # we skip this test, or it is on and then we run this test but warn

  if ( $marked_as_disabled )
  {
    if ( $::opt_enable_disabled )
    {
      $tinfo->{'dont_skip_though_disabled'}= 1;
    }
    else
    {
      $tinfo->{'skip'}= 1;
      $tinfo->{'disable'}= 1;   # Sub type of 'skip'
    }
  }

450 451 452 453 454
  if ( $component_id eq 'im' )
  {
    if ( $::glob_use_embedded_server )
    {
      $tinfo->{'skip'}= 1;
455
      $tinfo->{'comment'}= "No IM with embedded server";
456 457 458 459
    }
    elsif ( $::opt_ps_protocol )
    {
      $tinfo->{'skip'}= 1;
460
      $tinfo->{'comment'}= "No IM with --ps-protocol";
461
    }
unknown's avatar
unknown committed
462
    elsif ( $::opt_skip_im )
463 464
    {
      $tinfo->{'skip'}= 1;
465
      $tinfo->{'comment'}= "No IM tests(--skip-im)";
466 467
    }
  }
468 469 470
  else
  {
    mtr_options_from_test_file($tinfo,"$testdir/${tname}.test");
471

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
    if ( $tinfo->{'big_test'} and ! $::opt_big_test )
    {
      $tinfo->{'skip'}= 1;
      $tinfo->{'comment'}= "Test need 'big-test' option";
    }

    if ( $tinfo->{'ndb_extra'} and ! $::opt_ndb_extra_test )
    {
      $tinfo->{'skip'}= 1;
      $tinfo->{'comment'}= "Test need 'ndb_extra' option";
    }

    if ( $tinfo->{'require_manager'} )
    {
      $tinfo->{'skip'}= 1;
      $tinfo->{'comment'}= "Test need the _old_ manager(to be removed)";
    }

    if ( defined $tinfo->{'binlog_format'} and
	 ! ( $tinfo->{'binlog_format'} eq $::used_binlog_format ) )
    {
      $tinfo->{'skip'}= 1;
      $tinfo->{'comment'}= "Not running with binlog format '$tinfo->{'binlog_format'}'";
    }
unknown's avatar
unknown committed
496

497
    if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries )
unknown's avatar
unknown committed
498 499 500 501
    {
      $tinfo->{'skip'}= 1;
      $tinfo->{'comment'}= "Test need debug binaries";
    }
502
  }
503

unknown's avatar
unknown committed
504 505 506 507 508 509
  # We can't restart a running server that may be in use

  if ( $::glob_use_running_server and
       ( $tinfo->{'master_restart'} or $tinfo->{'slave_restart'} ) )
  {
    $tinfo->{'skip'}= 1;
510
    $tinfo->{'comment'}= "Can't restart a running server";
unknown's avatar
unknown committed
511
  }
512

unknown's avatar
unknown committed
513 514
}

515

unknown's avatar
unknown committed
516 517 518 519 520 521 522 523 524 525 526 527 528 529
# List of tags in the .test files that if found should set
# the specified value in "tinfo"
our @tags=
(
 ["include/have_innodb.inc", "innodb_test", 1],
 ["include/have_binlog_format_row.inc", "binlog_format", "row"],
 ["include/have_binlog_format_statement.inc", "binlog_format", "stmt"],
 ["include/big_test.inc", "big_test", 1],
 ["include/have_debug.inc", "need_debug", 1],
 ["include/have_ndb_extra.inc", "ndb_extra", 1],
 ["require_manager", "require_manager", 1],
);

sub mtr_options_from_test_file($$) {
530 531
  my $tinfo= shift;
  my $file= shift;
unknown's avatar
unknown committed
532 533
  #mtr_verbose("$file");
  my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!");
534

535
  while ( my $line= <$F> )
536 537 538
  {
    chomp;

539
    next if ( $line !~ /^--/ );
540

unknown's avatar
unknown committed
541 542
    # Match this line against tag in "tags" array
    foreach my $tag (@tags)
543
    {
544
      if ( index($line, $tag->[0]) >= 0 )
unknown's avatar
unknown committed
545 546 547 548
      {
	# Tag matched, assign value to "tinfo"
	$tinfo->{"$tag->[1]"}= $tag->[2];
      }
549 550
    }

551
    # If test sources another file, open it as well
552
    if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ )
553
    {
554
      my $value= $2;
unknown's avatar
unknown committed
555
      $value =~ s/^\s+//;  # Remove leading space
556
      $value =~ s/[[:space:]]+$//;  # Remove ending space
557 558 559 560 561 562 563

      my $sourced_file= "$::glob_mysql_test_dir/$value";
      mtr_options_from_test_file($tinfo, $sourced_file);
    }

  }
}
unknown's avatar
unknown committed
564 565

1;