Commit d99d05e9 authored by unknown's avatar unknown
Browse files

Implement WL#2789 "Instance Manager: test using mysql-test-run testing framework"


mysql-test/Makefile.am:
  Make installation procedure aware of the Instance Manager tests.
mysql-test/lib/mtr_cases.pl:
  Make collect_one_test_case() aware of the Instance Manager tests.
mysql-test/lib/mtr_process.pl:
  Minor changes:
    - open log files for append, not for overwrite. Append mode is very
      useful for debugging of several tests;
    - extract the code for killing processes into a separate function:
      mtr_kill_processes(). The function is used to stop IM-related processes.
mysql-test/mysql-test-run.pl:
  Added support for the Instance Manager tests.
parent 901075ac
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ dist-hook:
		$(distdir)/std_data $(distdir)/lib
	-$(INSTALL_DATA) $(srcdir)/t/*.def $(distdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.test $(distdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.imtest $(distdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.sql $(distdir)/t
	-$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t
@@ -73,6 +74,7 @@ install-data-local:
	$(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir)
	-$(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.imtest $(DESTDIR)$(testdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.sql $(DESTDIR)$(testdir)/t
	-$(INSTALL_DATA) $(srcdir)/t/*.disabled $(DESTDIR)$(testdir)/t
	$(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t
+108 −10
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ use File::Basename;
use strict;

sub collect_test_cases ($);
sub collect_one_test_case ($$$$$$);
sub collect_one_test_case ($$$$$$$);

##############################################################################
#
@@ -40,13 +40,84 @@ sub collect_test_cases ($) {
  if ( @::opt_cases )
  {
    foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
      $tname= basename($tname, ".test");
      my $elem= "$tname.test";
      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 ( $::glob_use_embedded_server )
        {
          mtr_report(
            "Instance Manager's tests are not available in embedded mode." .
            "Test case '$tname' is skipped.");
          next;
        }

        unless ( $::exe_im )
        {
          mtr_report(
            "Instance Manager executable is unavailable. " .
            "Test case '$tname' is skipped.");
          next;
        }
      }

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

      if ( defined $component_id )
      {
        if ( ! -f "$testdir/$elem")
        {
          mtr_error("Test case $tname ($testdir/$elem) is not found");
        }
      collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{});
      }
      else
      {
        my $mysqld_test_exists = -f "$testdir/$tname.test";
        my $im_test_exists = -f "$testdir/$tname.imtest";

        if ( $mysqld_test_exists && $im_test_exists )
        {
          mtr_error("Ambiguos test case name ($tname)");
        }
        elsif ( ! $mysqld_test_exists && !$im_test_exists )
        {
          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';
        }
      }
      
      collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{},
        $component_id);
    }
    closedir TESTDIR;
  }
@@ -70,11 +141,26 @@ sub collect_test_cases ($) {
    }

    foreach my $elem ( sort readdir(TESTDIR) ) {
      my $tname= mtr_match_extension($elem,"test");
      next if ! defined $tname;
      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;
      }
      
      next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test);

      collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled);
      collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
        $component_id);
    }
    closedir TESTDIR;
  }
@@ -112,13 +198,14 @@ sub collect_test_cases ($) {
##############################################################################


sub collect_one_test_case($$$$$$) {
sub collect_one_test_case($$$$$$$) {
  my $testdir= shift;
  my $resdir=  shift;
  my $tname=   shift;
  my $elem=    shift;
  my $cases=   shift;
  my $disabled=shift;
  my $component_id= shift;

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

@@ -138,6 +225,7 @@ sub collect_one_test_case($$$$$$) {
  my $tinfo= {};
  $tinfo->{'name'}= $tname;
  $tinfo->{'result_file'}= "$resdir/$tname.result";
  $tinfo->{'component_id'} = $component_id;
  push(@$cases, $tinfo);

  if ( $::opt_skip_test and defined mtr_match_prefix($tname,$::opt_skip_test) )
@@ -188,6 +276,7 @@ sub collect_one_test_case($$$$$$) {
  my $master_sh=       "$testdir/$tname-master.sh";
  my $slave_sh=        "$testdir/$tname-slave.sh";
  my $disabled_file=   "$testdir/$tname.disabled";
  my $im_opt_file=     "$testdir/$tname-im.opt";

  $tinfo->{'master_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
  $tinfo->{'slave_opt'}=  $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
@@ -290,6 +379,15 @@ sub collect_one_test_case($$$$$$) {
    }
  }

  if ( -f $im_opt_file )
  {
    $tinfo->{'im_opts'} = mtr_get_opts_from_file($im_opt_file);
  }
  else
  {
    $tinfo->{'im_opts'} = [];
  }

  # FIXME why this late?
  if ( $disabled->{$tname} )
  {
+56 −23
Original line number Diff line number Diff line
@@ -12,16 +12,17 @@ use strict;
#use POSIX ":sys_wait_h";
use POSIX 'WNOHANG';

sub mtr_run ($$$$$$);
sub mtr_spawn ($$$$$$);
sub mtr_run ($$$$$$;$);
sub mtr_spawn ($$$$$$;$);
sub mtr_stop_mysqld_servers ($);
sub mtr_kill_leftovers ();
sub mtr_record_dead_children ();
sub mtr_exit ($);
sub sleep_until_file_created ($$$);
sub mtr_kill_processes ($);

# static in C
sub spawn_impl ($$$$$$$);
sub spawn_impl ($$$$$$$$);

##############################################################################
#
@@ -32,37 +33,43 @@ sub spawn_impl ($$$$$$$);
# This function try to mimic the C version used in "netware/mysql_test_run.c"
# FIXME learn it to handle append mode as well, a "new" flag or a "append"

sub mtr_run ($$$$$$) {
sub mtr_run ($$$$$$;$) {
  my $path=       shift;
  my $arg_list_t= shift;
  my $input=      shift;
  my $output=     shift;
  my $error=      shift;
  my $pid_file=   shift;
  my $spawn_opts= shift;

  return spawn_impl($path,$arg_list_t,'run',$input,$output,$error,$pid_file);
  return spawn_impl($path,$arg_list_t,'run',$input,$output,$error,$pid_file,
    $spawn_opts);
}

sub mtr_run_test ($$$$$$) {
sub mtr_run_test ($$$$$$;$) {
  my $path=       shift;
  my $arg_list_t= shift;
  my $input=      shift;
  my $output=     shift;
  my $error=      shift;
  my $pid_file=   shift;
  my $spawn_opts= shift;

  return spawn_impl($path,$arg_list_t,'test',$input,$output,$error,$pid_file);
  return spawn_impl($path,$arg_list_t,'test',$input,$output,$error,$pid_file,
    $spawn_opts);
}

sub mtr_spawn ($$$$$$) {
sub mtr_spawn ($$$$$$;$) {
  my $path=       shift;
  my $arg_list_t= shift;
  my $input=      shift;
  my $output=     shift;
  my $error=      shift;
  my $pid_file=   shift;
  my $spawn_opts= shift;

  return spawn_impl($path,$arg_list_t,'spawn',$input,$output,$error,$pid_file);
  return spawn_impl($path,$arg_list_t,'spawn',$input,$output,$error,$pid_file,
    $spawn_opts);
}


@@ -72,7 +79,7 @@ sub mtr_spawn ($$$$$$) {
#
##############################################################################

sub spawn_impl ($$$$$$$) {
sub spawn_impl ($$$$$$$$) {
  my $path=       shift;
  my $arg_list_t= shift;
  my $mode=       shift;
@@ -80,6 +87,7 @@ sub spawn_impl ($$$$$$$) {
  my $output=     shift;
  my $error=      shift;
  my $pid_file=   shift;                 # FIXME
  my $spawn_opts= shift;

  if ( $::opt_script_debug )
  {
@@ -89,6 +97,18 @@ sub spawn_impl ($$$$$$$) {
    print STDERR "#### ", "STDOUT $output\n" if $output;
    print STDERR "#### ", "STDERR $error\n" if $error;
    print STDERR "#### ", "$mode : $path ", join(" ",@$arg_list_t), "\n";
    print STDERR "#### ", "spawn options:\n";
    if ($spawn_opts)
    {
      foreach my $key (sort keys %{$spawn_opts})
      {
        print STDERR "#### ", "  - $key: $spawn_opts->{$key}\n";
      }
    }
    else
    {
      print STDERR "#### ", "  none\n";
    }
    print STDERR "#### ", "-" x 78, "\n";
  }

@@ -135,9 +155,16 @@ sub spawn_impl ($$$$$$$) {
#       $ENV{'COMSPEC'}= "$::glob_cygwin_shell -c";
      }

      my $log_file_open_mode = '>';

      if ($spawn_opts and $spawn_opts->{'append_log_file'})
      {
        $log_file_open_mode = '>>';
      }

      if ( $output )
      {
        if ( ! open(STDOUT,">",$output) )
        if ( ! open(STDOUT,$log_file_open_mode,$output) )
        {
          mtr_error("can't redirect STDOUT to \"$output\": $!");
        }
@@ -154,7 +181,7 @@ sub spawn_impl ($$$$$$$) {
        }
        else
        {
          if ( ! open(STDERR,">",$error) )
          if ( ! open(STDERR,$log_file_open_mode,$error) )
          {
            mtr_error("can't redirect STDERR to \"$output\": $!");
          }
@@ -534,16 +561,7 @@ sub mtr_stop_mysqld_servers ($) {
  start_reap_all();                     # Avoid zombies

 SIGNAL:
  foreach my $sig (15,9)
  {
    my $retries= 20;                    # FIXME 20 seconds, this is silly!
    kill($sig, keys %mysqld_pids);
    while ( $retries-- and  kill(0, keys %mysqld_pids) )
    {
      mtr_debug("Sleep 1 second waiting for processes to die");
      sleep(1)                      # Wait one second
    }
  }
  mtr_kill_processes(\keys (%mysqld_pids));

  stop_reap_all();                      # Get into control again

@@ -805,7 +823,7 @@ sub sleep_until_file_created ($$$) {
    }

    # Check if it died after the fork() was successful 
    if ( waitpid($pid,&WNOHANG) == $pid )
    if ( $pid > 0 && waitpid($pid,&WNOHANG) == $pid )
    {
      return 0;
    }
@@ -826,6 +844,21 @@ sub sleep_until_file_created ($$$) {
}


sub mtr_kill_processes ($) {
  my $pids = shift;

  foreach my $sig (15,9)
  {
    my $retries= 20;                    # FIXME 20 seconds, this is silly!
    kill($sig, @{$pids});
    while ( $retries-- and  kill(0, @{$pids}) )
    {
      mtr_debug("Sleep 1 second waiting for processes to die");
      sleep(1)                      # Wait one second
    }
  }
}

##############################################################################
#
#  When we exit, we kill off all children
+307 −32
Original line number Diff line number Diff line
@@ -178,6 +178,7 @@ our $exe_mysqlshow; # Called from test case
our $exe_mysql_fix_system_tables;
our $exe_mysqltest;
our $exe_slave_mysqld;
our $exe_im;

our $opt_bench= 0;
our $opt_small_bench= 0;
@@ -216,12 +217,11 @@ our $opt_local_master;
our $master;                    # Will be struct in C
our $slave;

our $instance_manager;

our $opt_ndbcluster_port;
our $opt_ndbconnectstring;

our $opt_no_manager;            # Does nothing now, we never use manager
our $opt_manager_port;          # Does nothing now, we never use manager

our $opt_old_master;

our $opt_record;
@@ -309,6 +309,8 @@ sub mysqld_arguments ($$$$$);
sub stop_masters_slaves ();
sub stop_masters ();
sub stop_slaves ();
sub im_start ($$);
sub im_stop ($);
sub run_mysqltest ($);
sub usage ($);

@@ -460,6 +462,9 @@ sub command_line_setup () {
  my $opt_master_myport= 9306;
  my $opt_slave_myport=  9308;
  $opt_ndbcluster_port=  9350;
  my $im_port=           9310;
  my $im_mysqld1_port=   9312;
  my $im_mysqld2_port=   9314;

  # Read the command line
  # Note: Keep list, and the order, in sync with usage at end of this file
@@ -470,7 +475,6 @@ sub command_line_setup () {
             'ps-protocol'              => \$opt_ps_protocol,
             'bench'                    => \$opt_bench,
             'small-bench'              => \$opt_small_bench,
             'no-manager'               => \$opt_no_manager, # Currently not used

             # Control what test suites or cases to run
             'force'                    => \$opt_force,
@@ -485,7 +489,9 @@ sub command_line_setup () {
             'master_port=i'            => \$opt_master_myport,
             'slave_port=i'             => \$opt_slave_myport,
             'ndbcluster_port=i'        => \$opt_ndbcluster_port,
             'manager-port=i'           => \$opt_manager_port, # Currently not used
             'im-port=i'                => \$im_port, # Instance Manager port.
             'im-mysqld1-port=i'        => \$im_mysqld1_port, # Port of mysqld, controlled by IM
             'im-mysqld2-port=i'        => \$im_mysqld2_port, # Port of mysqld, controlled by IM

             # Test case authoring
             'record'                   => \$opt_record,
@@ -768,6 +774,37 @@ sub command_line_setup () {
  $slave->[2]->{'path_myport'}=    $opt_slave_myport + 2;
  $slave->[2]->{'start_timeout'}=  300;

  $instance_manager->{'path_err'}=        "$opt_vardir/log/im.err";
  $instance_manager->{'path_log'}=        "$opt_vardir/log/im.log";
  $instance_manager->{'path_pid'}=        "$opt_vardir/run/im.pid";
  $instance_manager->{'path_sock'}=       "$opt_tmpdir/im.sock";
  $instance_manager->{'port'}=            $im_port;
  $instance_manager->{'start_timeout'}=   $master->[0]->{'start_timeout'};
  $instance_manager->{'admin_login'}=     'im_admin';
  $instance_manager->{'admin_password'}=  'im_admin_secret';
  $instance_manager->{'admin_sha1'}=      '*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295';
  $instance_manager->{'password_file'}=   "$opt_vardir/im.passwd";
  $instance_manager->{'defaults_file'}=   "$opt_vardir/im.cnf";
  
  $instance_manager->{'instances'}->[0]->{'server_id'}= 1;
  $instance_manager->{'instances'}->[0]->{'port'}= $im_mysqld1_port;
  $instance_manager->{'instances'}->[0]->{'path_datadir'}=
    "$opt_vardir/im_mysqld_1.data";
  $instance_manager->{'instances'}->[0]->{'path_sock'}=
    "$opt_vardir/mysqld_1.sock";
  $instance_manager->{'instances'}->[0]->{'path_pid'}=
    "$opt_vardir/mysqld_1.pid";

  $instance_manager->{'instances'}->[1]->{'server_id'}= 2;
  $instance_manager->{'instances'}->[1]->{'port'}= $im_mysqld2_port;
  $instance_manager->{'instances'}->[1]->{'path_datadir'}=
    "$opt_vardir/im_mysqld_2.data";
  $instance_manager->{'instances'}->[1]->{'path_sock'}=
    "$opt_vardir/mysqld_2.sock";
  $instance_manager->{'instances'}->[1]->{'path_pid'}=
    "$opt_vardir/mysqld_2.pid";
  $instance_manager->{'instances'}->[1]->{'nonguarded'}= 1;

  if ( $opt_extern )
  {
    $glob_use_running_server=  1;
@@ -803,6 +840,9 @@ sub executable_setup () {
      $exe_mysqld=         mtr_exe_exists ("$glob_basedir/sql/mysqld");
      $path_language=      mtr_path_exists("$glob_basedir/sql/share/english/");
      $path_charsetsdir=   mtr_path_exists("$glob_basedir/sql/share/charsets");

      $exe_im= mtr_exe_exists(
        "$glob_basedir/server-tools/instance-manager/mysqlmanager");
    }

    if ( $glob_use_embedded_server )
@@ -850,6 +890,8 @@ sub executable_setup () {
    $exe_mysqld=         mtr_exe_exists ("$glob_basedir/libexec/mysqld",
                                         "$glob_basedir/bin/mysqld");

    $exe_im= mtr_exe_exists("$glob_basedir/libexec/mysqlmanager",
                            "$glob_basedir/bin/mysqlmanager");
    if ( $glob_use_embedded_server )
    {
      $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded");
@@ -923,6 +965,11 @@ sub environment_setup () {
# $ENV{'MYSQL_TCP_PORT'}=     '@MYSQL_TCP_PORT@'; # FIXME
  $ENV{'MYSQL_TCP_PORT'}=     3306;

  $ENV{'IM_MYSQLD1_SOCK'}=    $instance_manager->{instances}->[0]->{path_sock};
  $ENV{'IM_MYSQLD1_PORT'}=    $instance_manager->{instances}->[0]->{port};
  $ENV{'IM_MYSQLD2_SOCK'}=    $instance_manager->{instances}->[1]->{path_sock};
  $ENV{'IM_MYSQLD2_PORT'}=    $instance_manager->{instances}->[1]->{port};

  if ( $glob_cygwin_perl )
  {
    foreach my $key ('MYSQL_TEST_WINDIR','MASTER_MYSOCK')
@@ -1006,25 +1053,24 @@ sub kill_and_cleanup () {
  # FIXME do we really need to create these all, or are they
  # created for us when tables are created?

  rmtree("$master->[0]->{'path_myddir'}");
  mkpath("$master->[0]->{'path_myddir'}/mysql");
  mkpath("$master->[0]->{'path_myddir'}/test");

  rmtree("$master->[1]->{'path_myddir'}");
  mkpath("$master->[1]->{'path_myddir'}/mysql");
  mkpath("$master->[1]->{'path_myddir'}/test");
  my @data_dir_lst = (
    $master->[0]->{'path_myddir'},
    $master->[1]->{'path_myddir'},
    $slave->[0]->{'path_myddir'},
    $slave->[1]->{'path_myddir'},
    $slave->[2]->{'path_myddir'});
  
  rmtree("$slave->[0]->{'path_myddir'}");
  mkpath("$slave->[0]->{'path_myddir'}/mysql");
  mkpath("$slave->[0]->{'path_myddir'}/test");

  rmtree("$slave->[1]->{'path_myddir'}");
  mkpath("$slave->[1]->{'path_myddir'}/mysql");
  mkpath("$slave->[1]->{'path_myddir'}/test");
  foreach my $instance (@{$instance_manager->{'instances'}})
  {
    push (@data_dir_lst, $instance->{'path_datadir'});
  }

  rmtree("$slave->[2]->{'path_myddir'}");
  mkpath("$slave->[2]->{'path_myddir'}/mysql");
  mkpath("$slave->[2]->{'path_myddir'}/test");
  foreach my $data_dir (@data_dir_lst)
  {
    rmtree("$data_dir");
    mkpath("$data_dir/mysql");
    mkpath("$data_dir/test");
  }

  # To make some old test cases work, we create a soft
  # link from the old "var" location to the new one
@@ -1262,6 +1308,11 @@ sub mysql_install_db () {
  install_db('slave',  $slave->[1]->{'path_myddir'});
  install_db('slave',  $slave->[2]->{'path_myddir'});

  if ( defined $exe_im)
  {
    im_prepare_env($instance_manager);
  }

  if ( ndbcluster_install() )
  {
    # failed to install, disable usage but flag that its no ok
@@ -1336,6 +1387,101 @@ sub install_db ($$) {
}


sub im_prepare_env($) {
  my $instance_manager = shift;

  im_create_passwd_file($instance_manager);
  im_prepare_data_dir($instance_manager);
}


sub im_create_passwd_file($) {
  my $instance_manager = shift;

  my $pwd_file_path = $instance_manager->{'password_file'};
  
  mtr_report("Creating IM password file ($pwd_file_path)");
  
  open(OUT, ">", $pwd_file_path)
    or mtr_error("Can't write to $pwd_file_path: $!");
  
  print OUT $instance_manager->{'admin_login'}, ":",
        $instance_manager->{'admin_sha1'}, "\n";
  
  close(OUT);
}


sub im_create_defaults_file($) {
  my $instance_manager = shift;

  my $defaults_file = $instance_manager->{'defaults_file'};

  open(OUT, ">", $defaults_file)
    or mtr_error("Can't write to $defaults_file: $!");
  
  print OUT <<EOF
[mysql]

[manager]
pid-file            = $instance_manager->{path_pid}
socket              = $instance_manager->{path_sock}
port                = $instance_manager->{port}
password-file       = $instance_manager->{password_file}
default-mysqld-path = $exe_mysqld

EOF
;

  foreach my $instance (@{$instance_manager->{'instances'}})
  {
    my $server_id = $instance->{'server_id'};

    print OUT <<EOF
[mysqld$server_id]
socket              = $instance->{path_sock}
pid-file            = $instance->{path_pid}
port                = $instance->{port}
datadir             = $instance->{path_datadir}
log                 = $instance->{path_datadir}/mysqld$server_id.log
log-error           = $instance->{path_datadir}/mysqld$server_id.err.log
log-slow-queries    = $instance->{path_datadir}/mysqld$server_id.slow.log
language            = $path_language
character-sets-dir  = $path_charsetsdir
basedir             = $path_my_basedir
server_id           =$server_id
skip-stack-trace
skip-innodb
skip-bdb
skip-ndbcluster
EOF
;

    if ( exists $instance->{nonguarded} and
      defined $instance->{nonguarded} )
    {
      print OUT "nonguarded\n";
    }

    print OUT "\n";
  }

  close(OUT);
}


sub im_prepare_data_dir($) {
  my $instance_manager = shift;

  foreach my $instance (@{$instance_manager->{'instances'}})
  {
    install_db(
      'im_mysqld_' . $instance->{'server_id'},
      $instance->{'path_datadir'});
  }
}


##############################################################################
#
#  Run a single test case
@@ -1437,7 +1583,7 @@ sub run_testcase ($) {
    # FIXME split up start and check that started so that can do
    #       starts in parallel, masters and slaves at the same time.

    if ( ! $opt_local_master )
    if ( $tinfo->{'component_id'} eq 'mysqld' and ! $opt_local_master )
    {
      if ( $master->[0]->{'ndbcluster'} )
      {
@@ -1476,6 +1622,17 @@ sub run_testcase ($) {
        $master->[0]->{'running_master_is_special'}= 1;
      }
    }
    elsif ( $tinfo->{'component_id'} eq 'im')
    {
      # We have to create defaults file every time, in order to ensure that it
      # will be the same for each test. The problem is that test can change the
      # file (by SET/UNSET commands), so w/o recreating the file, execution of
      # one test can affect the other.

      im_create_defaults_file($instance_manager);

      im_start($instance_manager, $tinfo->{im_opts});
    }

    # ----------------------------------------------------------------------
    # Start slaves - if needed
@@ -1558,6 +1715,15 @@ sub run_testcase ($) {
      report_failure_and_restart($tinfo);
    }
  }

  # ----------------------------------------------------------------------
  # Stop Instance Manager if we are processing an IM-test case.
  # ----------------------------------------------------------------------

  if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' )
  {
    im_stop($instance_manager);
  }
}


@@ -1988,6 +2154,13 @@ sub mysqld_start ($$$$) {
sub stop_masters_slaves () {

  print  "Ending Tests\n";

  if (defined $instance_manager->{'pid'})
  {
    print  "Shutting-down Instance Manager\n";
    im_stop($instance_manager);
  }
  
  print  "Shutting-down MySQL daemon\n\n";
  stop_masters();
  print "Master(s) shutdown finished\n";
@@ -2046,6 +2219,97 @@ sub stop_slaves () {
  mtr_stop_mysqld_servers(\@args);
}

##############################################################################
#
#  Instance Manager management routines.
#
##############################################################################

sub im_start($$) {
  my $instance_manager = shift;
  my $opts = shift;

  if ( ! defined $exe_im)
  {
    return;
  }

  my $args;
  mtr_init_args(\$args);
  mtr_add_arg($args, "--defaults-file=" . $instance_manager->{'defaults_file'});

  foreach my $opt (@{$opts})
  {
    mtr_add_arg($args, $opt);
  }

  $instance_manager->{'pid'} = 
    mtr_spawn(
      $exe_im,                          # path to the executable
      $args,                            # cmd-line args
      '',                               # stdin
      $instance_manager->{'path_log'},  # stdout
      $instance_manager->{'path_err'},  # stderr
      '',                               # pid file path (not used)
      { append_log_file => 1 }          # append log files
      );

  if ( ! defined $instance_manager->{'pid'} )
  {
    mtr_report('Could not start Instance Manager');
    return;
  }
  
  # Instance Manager can be run in daemon mode. In this case, it creates
  # several processes and the parent process, created by mtr_spawn(), exits just
  # after start. So, we have to obtain Instance Manager PID from the PID file.

  sleep_until_file_created(
    $instance_manager->{'path_pid'},
    $instance_manager->{'start_timeout'},
    -1); # real PID is still unknown

  $instance_manager->{'pid'} =
    mtr_get_pid_from_file($instance_manager->{'path_pid'});
}

sub im_stop($) {
  my $instance_manager = shift;

  if (! defined $instance_manager->{'pid'})
  {
    return;
  }

  # Inspired from mtr_stop_mysqld_servers().

  start_reap_all();

  # Create list of pids. We should stop Instance Manager and all started
  # mysqld-instances. Some of them may be nonguarded, so IM will not stop them
  # on shutdown.

  my @pids = ( $instance_manager->{'pid'} );
  my $instances = $instance_manager->{'instances'};

  if ( -r $instances->[0]->{'path_pid'} )
  {
    push @pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'});
  }

  if ( -r $instances->[1]->{'path_pid'} )
  {
    push @pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'});
  }

  # Kill processes.

  mtr_kill_processes(\@pids);
  
  stop_reap_all();

  $instance_manager->{'pid'} = undef;
}

sub run_mysqltest ($) {
  my $tinfo=       shift;
@@ -2069,7 +2333,9 @@ sub run_mysqltest ($) {
  }

  my $cmdline_mysqlbinlog=
    "$exe_mysqlbinlog --no-defaults --local-load=$opt_tmpdir --character-sets-dir=$path_charsetsdir";
    "$exe_mysqlbinlog" .
      " --no-defaults --local-load=$opt_tmpdir" .
      " --character-sets-dir=$path_charsetsdir";

  if ( $opt_debug )
  {
@@ -2127,15 +2393,26 @@ sub run_mysqltest ($) {
  mtr_init_args(\$args);

  mtr_add_arg($args, "--no-defaults");
  mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
  mtr_add_arg($args, "--database=test");
  mtr_add_arg($args, "--user=%s", $opt_user);
  mtr_add_arg($args, "--password=");
  mtr_add_arg($args, "--silent");
  mtr_add_arg($args, "-v");
  mtr_add_arg($args, "--skip-safemalloc");
  mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);

  if ($tinfo->{'component_id'} eq 'im')
  {
    mtr_add_arg($args, "--socket=%s", $instance_manager->{'path_sock'});
    mtr_add_arg($args, "--port=%d", $instance_manager->{'port'});
    mtr_add_arg($args, "--user=%s", $instance_manager->{'admin_login'});
    mtr_add_arg($args, "--password=%s", $instance_manager->{'admin_password'});
  }
  else # component_id == mysqld
  {
    mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
    mtr_add_arg($args, "--port=%d", $master->[0]->{'path_myport'});
    mtr_add_arg($args, "--database=test");
    mtr_add_arg($args, "--user=%s", $opt_user);
    mtr_add_arg($args, "--password=");
  }

  if ( $opt_ps_protocol )
  {
@@ -2224,7 +2501,6 @@ Options to control what engine/variation to run
  ps-protocol           Use the binary protocol between client and server
  bench                 Run the benchmark suite FIXME
  small-bench           FIXME
  no-manager            Use the istanse manager (currently disabled)

Options to control what test suites or cases to run

@@ -2241,7 +2517,6 @@ Options that specify ports
  master_port=PORT      Specify the port number used by the first master
  slave_port=PORT       Specify the port number used by the first slave
  ndbcluster_port=PORT  Specify the port number used by cluster
  manager-port=PORT     Specify the port number used by manager (currently not used)

Options for test case authoring