1#!/usr/bin/perl
2# -*- cperl -*-
3
4# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License, version 2.0,
8# as published by the Free Software Foundation.
9#
10# This program is also distributed with certain software (including
11# but not limited to OpenSSL) that is licensed under separate terms,
12# as designated in a particular file or component or in included license
13# documentation.  The authors of MySQL hereby grant you an additional
14# permission to link the program and your derivative works with the
15# separately licensed software that they have included with MySQL.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20# GNU General Public License, version 2.0, for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26##############################################################################
27#
28#  mysql-test-run.pl
29#
30#  Tool used for executing a suite of .test file
31#
32#  See the "MySQL Test framework manual" for more information
33#  http://dev.mysql.com/doc/mysqltest/en/index.html
34#
35#  Please keep the test framework tools identical in all versions!
36#
37##############################################################################
38#
39# Coding style directions for this perl script
40#
41#   - To make this Perl script easy to alter even for those that not
42#     code Perl that often, keeep the coding style as close as possible to
43#     the C/C++ MySQL coding standard.
44#
45#   - All lists of arguments to send to commands are Perl lists/arrays,
46#     not strings we append args to. Within reason, most string
47#     concatenation for arguments should be avoided.
48#
49#   - Functions defined in the main program are not to be prefixed,
50#     functions in "library files" are to be prefixed with "mtr_" (for
51#     Mysql-Test-Run). There are some exceptions, code that fits best in
52#     the main program, but are put into separate files to avoid
53#     clutter, may be without prefix.
54#
55#   - All stat/opendir/-f/ is to be kept in collect_test_cases(). It
56#     will create a struct that the rest of the program can use to get
57#     the information. This separates the "find information" from the
58#     "do the work" and makes the program more easy to maintain.
59#
60#   - The rule when it comes to the logic of this program is
61#
62#       command_line_setup() - is to handle the logic between flags
63#       collect_test_cases() - is to do its best to select what tests
64#                              to run, dig out options, if needs restart etc.
65#       run_testcase()       - is to run a single testcase, and follow the
66#                              logic set in both above. No, or rare file
67#                              system operations. If a test seems complex,
68#                              it should probably not be here.
69#
70# A nice way to trace the execution of this script while debugging
71# is to use the Devel::Trace package found at
72# "http://www.plover.com/~mjd/perl/Trace/" and run this script like
73# "perl -d:Trace mysql-test-run.pl"
74#
75
76
77use lib "lib/v1/";
78
79$Devel::Trace::TRACE= 0;       # Don't trace boring init stuff
80
81#require 5.6.1;
82use File::Path;
83use File::Basename;
84use File::Copy;
85use File::Temp qw /tempdir/;
86use File::Spec::Functions qw /splitdir/;
87use Cwd;
88use Getopt::Long;
89use IO::Socket;
90use IO::Socket::INET;
91use strict;
92use warnings;
93
94select(STDOUT);
95$| = 1; # Automatically flush STDOUT
96
97our $glob_win32_perl=  ($^O eq "MSWin32"); # ActiveState Win32 Perl
98our $glob_cygwin_perl= ($^O eq "cygwin");  # Cygwin Perl
99our $glob_win32=       ($glob_win32_perl or $glob_cygwin_perl);
100
101require "lib/v1/mtr_cases.pl";
102require "lib/v1/mtr_im.pl";
103require "lib/v1/mtr_process.pl";
104require "lib/v1/mtr_timer.pl";
105require "lib/v1/mtr_io.pl";
106require "lib/v1/mtr_gcov.pl";
107require "lib/v1/mtr_gprof.pl";
108require "lib/v1/mtr_report.pl";
109require "lib/v1/mtr_match.pl";
110require "lib/v1/mtr_misc.pl";
111require "lib/v1/mtr_stress.pl";
112require "lib/v1/mtr_unique.pl";
113
114$Devel::Trace::TRACE= 1;
115
116##############################################################################
117#
118#  Default settings
119#
120##############################################################################
121
122# Misc global variables
123our $mysql_version_id;
124our $glob_mysql_test_dir=         undef;
125our $glob_mysql_bench_dir=        undef;
126our $glob_scriptname=             undef;
127our $glob_timers=                 undef;
128our $glob_use_embedded_server=    0;
129our @glob_test_mode;
130
131our $glob_basedir;
132our $glob_bindir;
133
134our $path_charsetsdir;
135our $path_client_bindir;
136our $path_client_libdir;
137our $path_share;
138our $path_language;
139our $path_timefile;
140our $path_snapshot;
141our $path_mysqltest_log;
142our $path_current_test_log;
143
144our $opt_vardir;                 # A path but set directly on cmd line
145our $path_vardir_trace;          # unix formatted opt_vardir for trace files
146our $opt_tmpdir;                 # A path but set directly on cmd line
147
148# Visual Studio produces executables in different sub-directories based on the
149# configuration used to build them.  To make life easier, an environment
150# variable or command-line option may be specified to control which set of
151# executables will be used by the test suite.
152our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
153
154our $default_vardir;
155
156our $opt_usage;
157our $opt_suites;
158our $opt_suites_default= "main,binlog,rpl"; # Default suites to run
159our $opt_script_debug= 0;  # Script debugging, enable with --script-debug
160our $opt_verbose= 0;  # Verbose output, enable with --verbose
161
162our $exe_master_mysqld;
163our $exe_mysql;
164our $exe_mysqladmin;
165our $exe_mysql_upgrade;
166our $exe_mysqlbinlog;
167our $exe_mysql_client_test;
168our $exe_bug25714;
169our $exe_mysqld;
170our $exe_mysqlcheck;
171our $exe_mysqldump;
172our $exe_mysqlslap;
173our $exe_mysqlimport;
174our $exe_mysqlshow;
175our $exe_mysql_config_editor;
176our $file_mysql_fix_privilege_tables;
177our $exe_mysqltest;
178our $exe_ndbd;
179our $exe_ndb_mgmd;
180our $exe_slave_mysqld;
181our $exe_my_print_defaults;
182our $exe_perror;
183our $lib_udf_example;
184our $lib_example_plugin;
185our $exe_libtool;
186
187our $opt_bench= 0;
188our $opt_small_bench= 0;
189our $opt_big_test= 0;
190
191our @opt_combinations;
192our $opt_skip_combination;
193
194our @opt_extra_mysqld_opt;
195
196our $opt_compress;
197our $opt_ssl;
198our $opt_skip_ssl;
199our $opt_ssl_supported;
200our $opt_ps_protocol;
201our $opt_sp_protocol;
202our $opt_cursor_protocol;
203our $opt_view_protocol;
204
205our $opt_debug;
206our $opt_do_test;
207our @opt_cases;                  # The test cases names in argv
208our $opt_embedded_server;
209
210our $opt_extern= 0;
211our $opt_socket;
212
213our $opt_fast;
214our $opt_force;
215our $opt_reorder= 0;
216our $opt_enable_disabled;
217our $opt_mem= $ENV{'MTR_MEM'};
218
219our $opt_gcov;
220our $opt_gcov_err;
221our $opt_gcov_msg;
222
223our $glob_debugger= 0;
224our $opt_gdb;
225our $opt_client_gdb;
226our $opt_ddd;
227our $opt_client_ddd;
228our $opt_manual_gdb;
229our $opt_manual_ddd;
230our $opt_manual_debug;
231our $opt_mtr_build_thread=0;
232our $opt_debugger;
233our $opt_client_debugger;
234
235our $opt_gprof;
236our $opt_gprof_dir;
237our $opt_gprof_master;
238our $opt_gprof_slave;
239
240our $master;
241our $slave;
242our $clusters;
243
244our $instance_manager;
245
246our $opt_master_myport;
247our $opt_slave_myport;
248our $im_port;
249our $im_mysqld1_port;
250our $im_mysqld2_port;
251our $opt_ndbcluster_port;
252our $opt_ndbconnectstring;
253our $opt_ndbcluster_port_slave;
254our $opt_ndbconnectstring_slave;
255
256our $opt_record;
257my $opt_report_features;
258our $opt_check_testcases;
259our $opt_mark_progress;
260
261our $opt_skip_rpl;
262our $max_slave_num= 0;
263our $max_master_num= 1;
264our $use_innodb;
265our $opt_skip_test;
266our $opt_skip_im;
267
268our $opt_sleep;
269
270our $opt_testcase_timeout;
271our $opt_suite_timeout;
272my  $default_testcase_timeout=     15; # 15 min max
273my  $default_suite_timeout=       300; # 5 hours max
274
275our $opt_start_and_exit;
276our $opt_start_dirty;
277our $opt_start_from;
278
279our $opt_strace_client;
280
281our $opt_timer= 1;
282
283our $opt_user;
284
285my $opt_valgrind= 0;
286my $opt_valgrind_mysqld= 0;
287my $opt_valgrind_mysqltest= 0;
288my @default_valgrind_args= ("--show-reachable=yes");
289my @valgrind_args;
290my $opt_valgrind_path;
291my $opt_callgrind;
292
293our $opt_stress=               "";
294our $opt_stress_suite=     "main";
295our $opt_stress_mode=    "random";
296our $opt_stress_threads=        5;
297our $opt_stress_test_count=     0;
298our $opt_stress_loop_count=     0;
299our $opt_stress_test_duration=  0;
300our $opt_stress_init_file=     "";
301our $opt_stress_test_file=     "";
302
303our $opt_warnings;
304
305our $opt_skip_ndbcluster= 0;
306our $opt_skip_ndbcluster_slave= 0;
307our $opt_with_ndbcluster= 0;
308our $opt_with_ndbcluster_only= 0;
309our $glob_ndbcluster_supported= 0;
310our $opt_ndb_extra_test= 0;
311our $opt_skip_master_binlog= 0;
312our $opt_skip_slave_binlog= 0;
313
314our $exe_ndb_mgm;
315our $exe_ndb_waiter;
316our $path_ndb_tools_dir;
317our $path_ndb_examples_dir;
318our $exe_ndb_example;
319our $path_ndb_testrun_log;
320
321our $path_sql_dir;
322
323our @data_dir_lst;
324
325our $used_binlog_format;
326our $used_default_engine;
327our $debug_compiled_binaries;
328
329our %mysqld_variables;
330
331my $source_dist= 0;
332
333our $opt_max_save_core= 5;
334my $num_saved_cores= 0;  # Number of core files saved in vardir/log/ so far.
335
336######################################################################
337#
338#  Function declarations
339#
340######################################################################
341
342sub main ();
343sub initial_setup ();
344sub command_line_setup ();
345sub set_mtr_build_thread_ports($);
346sub datadir_list_setup ();
347sub executable_setup ();
348sub environment_setup ();
349sub kill_running_servers ();
350sub remove_stale_vardir ();
351sub setup_vardir ();
352sub check_ssl_support ($);
353sub check_running_as_root();
354sub check_ndbcluster_support ($);
355sub rm_ndbcluster_tables ($);
356sub ndbcluster_start_install ($);
357sub ndbcluster_start ($$);
358sub ndbcluster_wait_started ($$);
359sub mysqld_wait_started($);
360sub run_benchmarks ($);
361sub initialize_servers ();
362sub mysql_install_db ();
363sub install_db ($$);
364sub copy_install_db ($$);
365sub run_testcase ($);
366sub run_testcase_stop_servers ($$$);
367sub run_testcase_start_servers ($);
368sub run_testcase_check_skip_test($);
369sub report_failure_and_restart ($);
370sub do_before_start_master ($);
371sub do_before_start_slave ($);
372sub ndbd_start ($$$);
373sub ndb_mgmd_start ($);
374sub mysqld_start ($$$);
375sub mysqld_arguments ($$$$);
376sub stop_all_servers ();
377sub run_mysqltest ($);
378sub usage ($);
379
380
381######################################################################
382#
383#  Main program
384#
385######################################################################
386
387main();
388
389sub main () {
390
391  command_line_setup();
392
393  check_ndbcluster_support(\%mysqld_variables);
394  check_ssl_support(\%mysqld_variables);
395  check_debug_support(\%mysqld_variables);
396
397  executable_setup();
398
399  environment_setup();
400  signal_setup();
401
402  if ( $opt_gcov )
403  {
404    gcov_prepare();
405  }
406
407  if ( $opt_gprof )
408  {
409    gprof_prepare();
410  }
411
412  if ( $opt_bench )
413  {
414    initialize_servers();
415    run_benchmarks(shift);      # Shift what? Extra arguments?!
416  }
417  elsif ( $opt_stress )
418  {
419    initialize_servers();
420    run_stress_test()
421  }
422  else
423  {
424    # Figure out which tests we are going to run
425    if (!$opt_suites)
426    {
427      $opt_suites= $opt_suites_default;
428
429      # Check for any extra suites to enable based on the path name
430      my %extra_suites=
431	(
432	 "mysql-5.1-new-ndb"              => "ndb_team",
433	 "mysql-5.1-new-ndb-merge"        => "ndb_team",
434	 "mysql-5.1-telco-6.2"            => "ndb_team",
435	 "mysql-5.1-telco-6.2-merge"      => "ndb_team",
436	 "mysql-5.1-telco-6.3"            => "ndb_team",
437	 "mysql-6.0-ndb"                  => "ndb_team",
438	);
439
440      foreach my $dir ( reverse splitdir($glob_basedir) )
441      {
442	my $extra_suite= $extra_suites{$dir};
443	if (defined $extra_suite){
444	  mtr_report("Found extra suite: $extra_suite");
445	  $opt_suites= "$extra_suite,$opt_suites";
446	  last;
447	}
448      }
449    }
450
451    my $tests= collect_test_cases($opt_suites);
452
453    # Turn off NDB and other similar options if no tests use it
454    my ($need_ndbcluster,$need_im);
455    foreach my $test (@$tests)
456    {
457      next if $test->{skip};
458
459      if (!$opt_extern)
460      {
461	$need_ndbcluster||= $test->{ndb_test};
462	$need_im||= $test->{component_id} eq 'im';
463
464	# Count max number of slaves used by a test case
465	if ( $test->{slave_num} > $max_slave_num) {
466	  $max_slave_num= $test->{slave_num};
467	  mtr_error("Too many slaves") if $max_slave_num > 3;
468	}
469
470	# Count max number of masters used by a test case
471	if ( $test->{master_num} > $max_master_num) {
472	  $max_master_num= $test->{master_num};
473	  mtr_error("Too many masters") if $max_master_num > 2;
474	  mtr_error("Too few masters") if $max_master_num < 1;
475	}
476      }
477      $use_innodb||= $test->{'innodb_test'};
478    }
479
480    # Check if cluster can be skipped
481    if ( !$need_ndbcluster )
482    {
483      $opt_skip_ndbcluster= 1;
484      $opt_skip_ndbcluster_slave= 1;
485    }
486
487    # Check if slave cluster can be skipped
488    if ($max_slave_num == 0)
489    {
490      $opt_skip_ndbcluster_slave= 1;
491    }
492
493    # Check if im can be skipped
494    if ( ! $need_im )
495    {
496     $opt_skip_im= 1;
497    }
498
499    initialize_servers();
500
501    if ( $opt_report_features ) {
502      run_report_features();
503    }
504
505    run_tests($tests);
506  }
507
508  mtr_exit(0);
509}
510
511##############################################################################
512#
513#  Default settings
514#
515##############################################################################
516
517#
518# When an option is no longer used by this program, it must be explicitly
519# ignored or else it will be passed through to mysqld.  GetOptions will call
520# this subroutine once for each such option on the command line.  See
521# Getopt::Long documentation.
522#
523
524sub warn_about_removed_option {
525  my ($option, $value, $hash_value) = @_;
526
527  warn "WARNING: This option is no longer used, and is ignored: --$option\n";
528}
529
530sub command_line_setup () {
531
532  # These are defaults for things that are set on the command line
533
534  my $opt_comment;
535
536  # Magic number -69.4 results in traditional test ports starting from 9306.
537  set_mtr_build_thread_ports(-69.4);
538
539  # If so requested, we try to avail ourselves of a unique build thread number.
540  if ( $ENV{'MTR_BUILD_THREAD'} ) {
541    if ( lc($ENV{'MTR_BUILD_THREAD'}) eq 'auto' ) {
542      print "Requesting build thread... ";
543      $ENV{'MTR_BUILD_THREAD'} = mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299);
544      print "got ".$ENV{'MTR_BUILD_THREAD'}."\n";
545    }
546  }
547
548  if ( $ENV{'MTR_BUILD_THREAD'} )
549  {
550    set_mtr_build_thread_ports($ENV{'MTR_BUILD_THREAD'});
551  }
552
553  # This is needed for test log evaluation in "gen-build-status-page"
554  # in all cases where the calling tool does not log the commands
555  # directly before it executes them, like "make test-force-pl" in RPM builds.
556  print "Logging: $0 ", join(" ", @ARGV), "\n";
557
558  # Read the command line
559  # Note: Keep list, and the order, in sync with usage at end of this file
560
561  # Options that are no longer used must still be processed, because all
562  # unprocessed options are passed directly to mysqld.  The user will be
563  # warned that the option is being ignored.
564  #
565  # Put the complete option string here.  For example, to remove the --suite
566  # option, remove it from GetOptions() below and put 'suite|suites=s' here.
567  my @removed_options = (
568  );
569
570  Getopt::Long::Configure("pass_through");
571  GetOptions(
572             # Control what engine/variation to run
573             'embedded-server'          => \$opt_embedded_server,
574             'ps-protocol'              => \$opt_ps_protocol,
575             'sp-protocol'              => \$opt_sp_protocol,
576             'view-protocol'            => \$opt_view_protocol,
577             'cursor-protocol'          => \$opt_cursor_protocol,
578             'ssl|with-openssl'         => \$opt_ssl,
579             'skip-ssl'                 => \$opt_skip_ssl,
580             'compress'                 => \$opt_compress,
581             'bench'                    => \$opt_bench,
582             'small-bench'              => \$opt_small_bench,
583             'with-ndbcluster|ndb'      => \$opt_with_ndbcluster,
584             'vs-config'            => \$opt_vs_config,
585
586             # Control what test suites or cases to run
587             'force'                    => \$opt_force,
588             'with-ndbcluster-only'     => \$opt_with_ndbcluster_only,
589             'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
590             'skip-ndbcluster-slave|skip-ndb-slave'
591                                        => \$opt_skip_ndbcluster_slave,
592             'ndb-extra-test'           => \$opt_ndb_extra_test,
593             'skip-master-binlog'       => \$opt_skip_master_binlog,
594             'skip-slave-binlog'        => \$opt_skip_slave_binlog,
595             'do-test=s'                => \$opt_do_test,
596             'start-from=s'             => \$opt_start_from,
597             'suite|suites=s'           => \$opt_suites,
598             'skip-rpl'                 => \$opt_skip_rpl,
599             'skip-im'                  => \$opt_skip_im,
600             'skip-test=s'              => \$opt_skip_test,
601             'big-test'                 => \$opt_big_test,
602             'combination=s'            => \@opt_combinations,
603             'skip-combination'         => \$opt_skip_combination,
604
605             # Specify ports
606             'master_port=i'            => \$opt_master_myport,
607             'slave_port=i'             => \$opt_slave_myport,
608             'ndbcluster-port|ndbcluster_port=i' => \$opt_ndbcluster_port,
609             'ndbcluster-port-slave=i'  => \$opt_ndbcluster_port_slave,
610             'im-port=i'                => \$im_port, # Instance Manager port.
611             'im-mysqld1-port=i'        => \$im_mysqld1_port, # Port of mysqld, controlled by IM
612             'im-mysqld2-port=i'        => \$im_mysqld2_port, # Port of mysqld, controlled by IM
613	     'mtr-build-thread=i'       => \$opt_mtr_build_thread,
614
615             # Test case authoring
616             'record'                   => \$opt_record,
617             'check-testcases'          => \$opt_check_testcases,
618             'mark-progress'            => \$opt_mark_progress,
619
620             # Extra options used when starting mysqld
621             'mysqld=s'                 => \@opt_extra_mysqld_opt,
622
623             # Run test on running server
624             'extern'                   => \$opt_extern,
625             'ndb-connectstring=s'       => \$opt_ndbconnectstring,
626             'ndb-connectstring-slave=s' => \$opt_ndbconnectstring_slave,
627
628             # Debugging
629             'gdb'                      => \$opt_gdb,
630             'client-gdb'               => \$opt_client_gdb,
631             'manual-gdb'               => \$opt_manual_gdb,
632             'manual-debug'             => \$opt_manual_debug,
633             'ddd'                      => \$opt_ddd,
634             'client-ddd'               => \$opt_client_ddd,
635             'manual-ddd'               => \$opt_manual_ddd,
636	     'debugger=s'               => \$opt_debugger,
637	     'client-debugger=s'        => \$opt_client_debugger,
638             'strace-client'            => \$opt_strace_client,
639             'master-binary=s'          => \$exe_master_mysqld,
640             'slave-binary=s'           => \$exe_slave_mysqld,
641             'max-save-core=i'          => \$opt_max_save_core,
642
643             # Coverage, profiling etc
644             'gcov'                     => \$opt_gcov,
645             'gprof'                    => \$opt_gprof,
646             'valgrind|valgrind-all'    => \$opt_valgrind,
647             'valgrind-mysqltest'       => \$opt_valgrind_mysqltest,
648             'valgrind-mysqld'          => \$opt_valgrind_mysqld,
649             'valgrind-options=s'       => sub {
650	       my ($opt, $value)= @_;
651	       # Deprecated option unless it's what we know pushbuild uses
652	       if ($value eq "--gen-suppressions=all --show-reachable=yes") {
653		 push(@valgrind_args, $_) for (split(' ', $value));
654		 return;
655	       }
656	       die("--valgrind-options=s is deprecated. Use ",
657		   "--valgrind-option=s, to be specified several",
658		   " times if necessary");
659	     },
660             'valgrind-option=s'        => \@valgrind_args,
661             'valgrind-path=s'          => \$opt_valgrind_path,
662	     'callgrind'                => \$opt_callgrind,
663
664             # Stress testing
665             'stress'                   => \$opt_stress,
666             'stress-suite=s'           => \$opt_stress_suite,
667             'stress-threads=i'         => \$opt_stress_threads,
668             'stress-test-file=s'       => \$opt_stress_test_file,
669             'stress-init-file=s'       => \$opt_stress_init_file,
670             'stress-mode=s'            => \$opt_stress_mode,
671             'stress-loop-count=i'      => \$opt_stress_loop_count,
672             'stress-test-count=i'      => \$opt_stress_test_count,
673             'stress-test-duration=i'   => \$opt_stress_test_duration,
674
675	     # Directories
676             'tmpdir=s'                 => \$opt_tmpdir,
677             'vardir=s'                 => \$opt_vardir,
678             'benchdir=s'               => \$glob_mysql_bench_dir,
679             'mem'                      => \$opt_mem,
680             'client-bindir=s'          => \$path_client_bindir,
681             'client-libdir=s'          => \$path_client_libdir,
682
683             # Misc
684             'report-features'          => \$opt_report_features,
685             'comment=s'                => \$opt_comment,
686             'debug'                    => \$opt_debug,
687             'fast'                     => \$opt_fast,
688             'reorder'                  => \$opt_reorder,
689             'enable-disabled'          => \$opt_enable_disabled,
690             'script-debug'             => \$opt_script_debug,
691             'verbose'                  => \$opt_verbose,
692             'sleep=i'                  => \$opt_sleep,
693             'socket=s'                 => \$opt_socket,
694             'start-dirty'              => \$opt_start_dirty,
695             'start-and-exit'           => \$opt_start_and_exit,
696             'timer!'                   => \$opt_timer,
697             'user=s'                   => \$opt_user,
698             'testcase-timeout=i'       => \$opt_testcase_timeout,
699             'suite-timeout=i'          => \$opt_suite_timeout,
700             'warnings|log-warnings'    => \$opt_warnings,
701
702             # Options which are no longer used
703             (map { $_ => \&warn_about_removed_option } @removed_options),
704
705             'help|h'                   => \$opt_usage,
706            ) or usage("Can't read options");
707
708  usage("") if $opt_usage;
709
710  $glob_scriptname=  basename($0);
711
712  if ($opt_mtr_build_thread != 0)
713  {
714    set_mtr_build_thread_ports($opt_mtr_build_thread)
715  }
716  elsif ($ENV{'MTR_BUILD_THREAD'})
717  {
718    $opt_mtr_build_thread= $ENV{'MTR_BUILD_THREAD'};
719  }
720
721  # We require that we are in the "mysql-test" directory
722  # to run mysql-test-run
723  if (! -f $glob_scriptname)
724  {
725    mtr_error("Can't find the location for the mysql-test-run script\n" .
726              "Go to to the mysql-test directory and execute the script " .
727              "as follows:\n./$glob_scriptname");
728  }
729
730  if ( -d "../sql" )
731  {
732    $source_dist=  1;
733  }
734
735  # Find the absolute path to the test directory
736  $glob_mysql_test_dir=  cwd();
737  if ( $glob_cygwin_perl )
738  {
739    # Windows programs like 'mysqld' needs Windows paths
740    $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`;
741    chomp($glob_mysql_test_dir);
742  }
743  if (defined $ENV{MTR_BINDIR})
744  {
745    $default_vardir= "$ENV{MTR_BINDIR}/mysql-test/var";
746  }
747  else
748  {
749    $default_vardir= "$glob_mysql_test_dir/var";
750  }
751
752  # In most cases, the base directory we find everything relative to,
753  # is the parent directory of the "mysql-test" directory. For source
754  # distributions, TAR binary distributions and some other packages.
755  $glob_basedir= dirname($glob_mysql_test_dir);
756
757  $glob_bindir= $ENV{'MTR_BINDIR'} || $glob_basedir;
758  # In the RPM case, binaries and libraries are installed in the
759  # default system locations, instead of having our own private base
760  # directory. And we install "/usr/share/mysql-test". Moving up one
761  # more directory relative to "mysql-test" gives us a usable base
762  # directory for RPM installs.
763  if ( ! $source_dist and ! -d "$glob_basedir/bin" )
764  {
765    $glob_basedir= dirname($glob_basedir);
766  }
767
768  # Expect mysql-bench to be located adjacent to the source tree, by default
769  $glob_mysql_bench_dir= "$glob_basedir/../mysql-bench"
770    unless defined $glob_mysql_bench_dir;
771  $glob_mysql_bench_dir= undef
772    unless -d $glob_mysql_bench_dir;
773
774
775  $glob_timers= mtr_init_timers();
776
777  # --------------------------------------------------------------------------
778  # Embedded server flag
779  # --------------------------------------------------------------------------
780  if ( $opt_embedded_server )
781  {
782    $glob_use_embedded_server= 1;
783    # Add the location for libmysqld.dll to the path.
784    if ( $glob_win32 )
785    {
786      my $lib_mysqld=
787        mtr_path_exists(vs_config_dirs('libmysqld',''));
788	  $lib_mysqld= $glob_cygwin_perl ? ":".`cygpath "$lib_mysqld"`
789                                     : ";".$lib_mysqld;
790      chomp($lib_mysqld);
791      $ENV{'PATH'}="$ENV{'PATH'}".$lib_mysqld;
792    }
793
794    push(@glob_test_mode, "embedded");
795    $opt_skip_rpl= 1;              # We never run replication with embedded
796    $opt_skip_ndbcluster= 1;       # Turn off use of NDB cluster
797    $opt_skip_ssl= 1;              # Turn off use of SSL
798
799    # Turn off use of bin log
800    push(@opt_extra_mysqld_opt, "--skip-log-bin");
801
802    if ( $opt_extern )
803    {
804      mtr_error("Can't use --extern with --embedded-server");
805    }
806  }
807
808  #
809  # Find the mysqld executable to be able to find the mysqld version
810  # number as early as possible
811  #
812
813  # Look for the client binaries directory
814  if ($path_client_bindir)
815  {
816    # --client-bindir=path set on command line, check that the path exists
817    $path_client_bindir= mtr_path_exists($path_client_bindir);
818  }
819  else
820  {
821    $path_client_bindir= mtr_path_exists("$glob_bindir/client_release",
822					 "$glob_bindir/client_debug",
823					 vs_config_dirs('client', ''),
824					 "$glob_bindir/client",
825					 "$glob_bindir/bin");
826  }
827
828  # Look for language files and charsetsdir, use same share
829  $path_share=      mtr_path_exists("$glob_bindir/share/mysql",
830                                    "$glob_bindir/sql/share",
831                                    "$glob_bindir/share");
832
833  $path_language=      mtr_path_exists("$path_share");
834  $path_charsetsdir =   mtr_path_exists("$glob_basedir/share/mysql/charsets",
835                                    "$glob_basedir/sql/share/charsets",
836                                    "$glob_basedir/share/charsets");
837
838  if (!$opt_extern)
839  {
840    $exe_mysqld=       mtr_exe_exists (vs_config_dirs('sql', 'mysqld'),
841                                       vs_config_dirs('sql', 'mysqld-debug'),
842				       "$glob_bindir/sql/mysqld",
843				       "$path_client_bindir/mysqld-max-nt",
844				       "$path_client_bindir/mysqld-max",
845				       "$path_client_bindir/mysqld-nt",
846				       "$path_client_bindir/mysqld",
847				       "$path_client_bindir/mysqld-debug",
848				       "$path_client_bindir/mysqld-max",
849				       "$glob_bindir/libexec/mysqld",
850				       "$glob_bindir/bin/mysqld",
851				       "$glob_bindir/sbin/mysqld");
852
853    # Use the mysqld found above to find out what features are available
854    collect_mysqld_features();
855  }
856  else
857  {
858    $mysqld_variables{'port'}= 3306;
859    $mysqld_variables{'master-port'}= 3306;
860  }
861
862  if ( $opt_comment )
863  {
864    print "\n";
865    print '#' x 78, "\n";
866    print "# $opt_comment\n";
867    print '#' x 78, "\n\n";
868  }
869
870  foreach my $arg ( @ARGV )
871  {
872    if ( $arg =~ /^--skip-/ )
873    {
874      push(@opt_extra_mysqld_opt, $arg);
875    }
876    elsif ( $arg =~ /^--$/ )
877    {
878      # It is an effect of setting 'pass_through' in option processing
879      # that the lone '--' separating options from arguments survives,
880      # simply ignore it.
881    }
882    elsif ( $arg =~ /^-/ )
883    {
884      usage("Invalid option \"$arg\"");
885    }
886    else
887    {
888      push(@opt_cases, $arg);
889    }
890  }
891
892  # --------------------------------------------------------------------------
893  # Find out type of logging that are being used
894  # --------------------------------------------------------------------------
895  if (!$opt_extern && $mysql_version_id >= 50100 )
896  {
897    foreach my $arg ( @opt_extra_mysqld_opt )
898    {
899      if ( $arg =~ /binlog[-_]format=(\S+)/ )
900      {
901      	$used_binlog_format= $1;
902      }
903    }
904    if (defined $used_binlog_format)
905    {
906      mtr_report("Using binlog format '$used_binlog_format'");
907    }
908    else
909    {
910      mtr_report("Using dynamic switching of binlog format");
911    }
912  }
913
914
915  # --------------------------------------------------------------------------
916  # Find out default storage engine being used(if any)
917  # --------------------------------------------------------------------------
918  if ( $opt_with_ndbcluster )
919  {
920    # --ndb or --with-ndbcluster turns on --default-storage-engine=ndbcluster
921    push(@opt_extra_mysqld_opt, "--default-storage-engine=ndbcluster");
922  }
923
924  foreach my $arg ( @opt_extra_mysqld_opt )
925  {
926    if ( $arg =~ /default-storage-engine=(\S+)/ )
927    {
928      $used_default_engine= $1;
929    }
930  }
931  mtr_report("Using default engine '$used_default_engine'")
932    if defined $used_default_engine;
933
934  if ($glob_win32 and defined $opt_mem) {
935    mtr_report("--mem not supported on Windows, ignored");
936    $opt_mem= undef;
937  }
938
939  # --------------------------------------------------------------------------
940  # Check if we should speed up tests by trying to run on tmpfs
941  # --------------------------------------------------------------------------
942  if ( defined $opt_mem )
943  {
944    mtr_error("Can't use --mem and --vardir at the same time ")
945      if $opt_vardir;
946    mtr_error("Can't use --mem and --tmpdir at the same time ")
947      if $opt_tmpdir;
948
949    # Search through list of locations that are known
950    # to be "fast disks" to list to find a suitable location
951    # Use --mem=<dir> as first location to look.
952    my @tmpfs_locations= ($opt_mem, "/dev/shm", "/tmp");
953
954    foreach my $fs (@tmpfs_locations)
955    {
956      if ( -d $fs )
957      {
958	mtr_report("Using tmpfs in $fs");
959	$opt_mem= "$fs/var";
960	$opt_mem .= $opt_mtr_build_thread if $opt_mtr_build_thread;
961	last;
962      }
963    }
964  }
965
966  # --------------------------------------------------------------------------
967  # Set the "var/" directory, as it is the base for everything else
968  # --------------------------------------------------------------------------
969  if ( ! $opt_vardir )
970  {
971    $opt_vardir= $default_vardir;
972  }
973  elsif ( $mysql_version_id < 50000 and
974	  $opt_vardir ne $default_vardir)
975  {
976    # Version 4.1 and --vardir was specified
977    # Only supported as a symlink from var/
978    # by setting up $opt_mem that symlink will be created
979    if ( ! $glob_win32 )
980    {
981      # Only platforms that have native symlinks can use the vardir trick
982      $opt_mem= $opt_vardir;
983      mtr_report("Using 4.1 vardir trick");
984    }
985
986    $opt_vardir= $default_vardir;
987  }
988
989  $path_vardir_trace= $opt_vardir;
990  # Chop off any "c:", DBUG likes a unix path ex: c:/src/... => /src/...
991  $path_vardir_trace=~ s/^\w://;
992
993  # We make the path absolute, as the server will do a chdir() before usage
994  unless ( $opt_vardir =~ m,^/, or
995           ($glob_win32 and $opt_vardir =~ m,^[a-z]:/,i) )
996  {
997    # Make absolute path, relative test dir
998    $opt_vardir= "$glob_mysql_test_dir/$opt_vardir";
999  }
1000
1001  # --------------------------------------------------------------------------
1002  # Set tmpdir
1003  # --------------------------------------------------------------------------
1004  $opt_tmpdir=       "$opt_vardir/tmp" unless $opt_tmpdir;
1005  $opt_tmpdir =~ s,/+$,,;       # Remove ending slash if any
1006
1007  # --------------------------------------------------------------------------
1008  # Check im suport
1009  # --------------------------------------------------------------------------
1010  if ($opt_extern)
1011  {
1012    mtr_report("Disable instance manager when running with extern mysqld");
1013    $opt_skip_im= 1;
1014  }
1015  elsif ( $mysql_version_id < 50000 )
1016  {
1017    # Instance manager is not supported until 5.0
1018    $opt_skip_im= 1;
1019  }
1020  elsif ( $glob_win32 )
1021  {
1022    mtr_report("Disable Instance manager - testing not supported on Windows");
1023    $opt_skip_im= 1;
1024  }
1025
1026  # --------------------------------------------------------------------------
1027  # Record flag
1028  # --------------------------------------------------------------------------
1029  if ( $opt_record and ! @opt_cases )
1030  {
1031    mtr_error("Will not run in record mode without a specific test case");
1032  }
1033
1034  if ( $opt_record )
1035  {
1036    $opt_skip_combination = 1;
1037  }
1038
1039  # --------------------------------------------------------------------------
1040  # ps protcol flag
1041  # --------------------------------------------------------------------------
1042  if ( $opt_ps_protocol )
1043  {
1044    push(@glob_test_mode, "ps-protocol");
1045  }
1046
1047  # --------------------------------------------------------------------------
1048  # Bench flags
1049  # --------------------------------------------------------------------------
1050  if ( $opt_small_bench )
1051  {
1052    $opt_bench=  1;
1053  }
1054
1055  # --------------------------------------------------------------------------
1056  # Big test flags
1057  # --------------------------------------------------------------------------
1058   if ( $opt_big_test )
1059   {
1060     $ENV{'BIG_TEST'}= 1;
1061   }
1062
1063  # --------------------------------------------------------------------------
1064  # Gcov flag
1065  # --------------------------------------------------------------------------
1066  if ( $opt_gcov and ! $source_dist )
1067  {
1068    mtr_error("Coverage test needs the source - please use source dist");
1069  }
1070
1071  # --------------------------------------------------------------------------
1072  # Check debug related options
1073  # --------------------------------------------------------------------------
1074  if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd ||
1075       $opt_manual_gdb || $opt_manual_ddd || $opt_manual_debug ||
1076       $opt_debugger || $opt_client_debugger )
1077  {
1078    # Indicate that we are using debugger
1079    $glob_debugger= 1;
1080    if ( $opt_extern )
1081    {
1082      mtr_error("Can't use --extern when using debugger");
1083    }
1084  }
1085
1086  # --------------------------------------------------------------------------
1087  # Check if special exe was selected for master or slave
1088  # --------------------------------------------------------------------------
1089  $exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
1090  $exe_slave_mysqld=  $exe_slave_mysqld  || $exe_mysqld;
1091
1092  # --------------------------------------------------------------------------
1093  # Check valgrind arguments
1094  # --------------------------------------------------------------------------
1095  if ( $opt_valgrind or $opt_valgrind_path or @valgrind_args)
1096  {
1097    mtr_report("Turning on valgrind for all executables");
1098    $opt_valgrind= 1;
1099    $opt_valgrind_mysqld= 1;
1100    $opt_valgrind_mysqltest= 1;
1101  }
1102  elsif ( $opt_valgrind_mysqld )
1103  {
1104    mtr_report("Turning on valgrind for mysqld(s) only");
1105    $opt_valgrind= 1;
1106  }
1107  elsif ( $opt_valgrind_mysqltest )
1108  {
1109    mtr_report("Turning on valgrind for mysqltest and mysql_client_test only");
1110    $opt_valgrind= 1;
1111  }
1112
1113  if ( $opt_callgrind )
1114  {
1115    mtr_report("Turning on valgrind with callgrind for mysqld(s)");
1116    $opt_valgrind= 1;
1117    $opt_valgrind_mysqld= 1;
1118
1119    # Set special valgrind options unless options passed on command line
1120    push(@valgrind_args, "--trace-children=yes")
1121      unless @valgrind_args;
1122  }
1123
1124  if ( $opt_valgrind )
1125  {
1126    # Set valgrind_options to default unless already defined
1127    push(@valgrind_args, @default_valgrind_args)
1128      unless @valgrind_args;
1129
1130    mtr_report("Running valgrind with options \"",
1131	       join(" ", @valgrind_args), "\"");
1132  }
1133
1134  if ( ! $opt_testcase_timeout )
1135  {
1136    $opt_testcase_timeout=
1137      $ENV{MTR_TESTCASE_TIMEOUT} || $default_testcase_timeout;
1138    $opt_testcase_timeout*= 10 if $opt_valgrind;
1139    $opt_testcase_timeout*= 10 if ($opt_debug and $glob_win32);
1140  }
1141
1142  if ( ! $opt_suite_timeout )
1143  {
1144    $opt_suite_timeout=
1145      $ENV{MTR_SUITE_TIMEOUT} || $default_suite_timeout;
1146    $opt_suite_timeout*= 6 if $opt_valgrind;
1147    $opt_suite_timeout*= 6 if ($opt_debug and $glob_win32);
1148  }
1149
1150  if ( ! $opt_user )
1151  {
1152    if ( $opt_extern )
1153    {
1154      $opt_user= "test";
1155    }
1156    else
1157    {
1158      $opt_user= "root"; # We want to do FLUSH xxx commands
1159    }
1160  }
1161
1162  # On QNX, /tmp/dir/master.sock and /tmp/dir//master.sock seem to be
1163  # considered different, so avoid the extra slash (/) in the socket
1164  # paths.
1165  my $sockdir = $opt_tmpdir;
1166  $sockdir =~ s|/+$||;
1167
1168  # On some operating systems, there is a limit to the length of a
1169  # UNIX domain socket's path far below PATH_MAX, so try to avoid long
1170  # socket path names.
1171  $sockdir = tempdir(CLEANUP => 0) if ( length($sockdir) >= 70 );
1172
1173  $master->[0]=
1174  {
1175   pid           => 0,
1176   type          => "master",
1177   idx           => 0,
1178   path_myddir   => "$opt_vardir/master-data",
1179   path_myerr    => "$opt_vardir/log/master.err",
1180   path_pid    => "$opt_vardir/run/master.pid",
1181   path_sock   => "$sockdir/master.sock",
1182   port   =>  $opt_master_myport,
1183   start_timeout =>  400, # enough time create innodb tables
1184   cluster       =>  0, # index in clusters list
1185   start_opts    => [],
1186  };
1187
1188  $master->[1]=
1189  {
1190   pid           => 0,
1191   type          => "master",
1192   idx           => 1,
1193   path_myddir   => "$opt_vardir/master1-data",
1194   path_myerr    => "$opt_vardir/log/master1.err",
1195   path_pid    => "$opt_vardir/run/master1.pid",
1196   path_sock   => "$sockdir/master1.sock",
1197   port   => $opt_master_myport + 1,
1198   start_timeout => 400, # enough time create innodb tables
1199   cluster       =>  0, # index in clusters list
1200   start_opts    => [],
1201  };
1202
1203  $slave->[0]=
1204  {
1205   pid           => 0,
1206   type          => "slave",
1207   idx           => 0,
1208   path_myddir   => "$opt_vardir/slave-data",
1209   path_myerr    => "$opt_vardir/log/slave.err",
1210   path_pid    => "$opt_vardir/run/slave.pid",
1211   path_sock   => "$sockdir/slave.sock",
1212   port   => $opt_slave_myport,
1213   start_timeout => 400,
1214
1215   cluster       =>  1, # index in clusters list
1216   start_opts    => [],
1217  };
1218
1219  $slave->[1]=
1220  {
1221   pid           => 0,
1222   type          => "slave",
1223   idx           => 1,
1224   path_myddir   => "$opt_vardir/slave1-data",
1225   path_myerr    => "$opt_vardir/log/slave1.err",
1226   path_pid    => "$opt_vardir/run/slave1.pid",
1227   path_sock   => "$sockdir/slave1.sock",
1228   port   => $opt_slave_myport + 1,
1229   start_timeout => 300,
1230   cluster       =>  -1, # index in clusters list
1231   start_opts    => [],
1232  };
1233
1234  $slave->[2]=
1235  {
1236   pid           => 0,
1237   type          => "slave",
1238   idx           => 2,
1239   path_myddir   => "$opt_vardir/slave2-data",
1240   path_myerr    => "$opt_vardir/log/slave2.err",
1241   path_pid    => "$opt_vardir/run/slave2.pid",
1242   path_sock   => "$sockdir/slave2.sock",
1243   port   => $opt_slave_myport + 2,
1244   start_timeout => 300,
1245   cluster       =>  -1, # index in clusters list
1246   start_opts    => [],
1247  };
1248
1249  $instance_manager=
1250  {
1251   path_err =>        "$opt_vardir/log/im.err",
1252   path_log =>        "$opt_vardir/log/im.log",
1253   path_pid =>        "$opt_vardir/run/im.pid",
1254   path_angel_pid =>  "$opt_vardir/run/im.angel.pid",
1255   path_sock =>       "$sockdir/im.sock",
1256   port =>            $im_port,
1257   start_timeout =>   $master->[0]->{'start_timeout'},
1258   admin_login =>     'im_admin',
1259   admin_password =>  'im_admin_secret',
1260   admin_sha1 =>      '*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295',
1261   password_file =>   "$opt_vardir/im.passwd",
1262   defaults_file =>   "$opt_vardir/im.cnf",
1263  };
1264
1265  $instance_manager->{'instances'}->[0]=
1266  {
1267   server_id    => 1,
1268   port         => $im_mysqld1_port,
1269   path_datadir => "$opt_vardir/im_mysqld_1.data",
1270   path_sock    => "$sockdir/mysqld_1.sock",
1271   path_pid     => "$opt_vardir/run/mysqld_1.pid",
1272   start_timeout  => 400, # enough time create innodb tables
1273   old_log_format => 1
1274  };
1275
1276  $instance_manager->{'instances'}->[1]=
1277  {
1278   server_id    => 2,
1279   port         => $im_mysqld2_port,
1280   path_datadir => "$opt_vardir/im_mysqld_2.data",
1281   path_sock    => "$sockdir/mysqld_2.sock",
1282   path_pid     => "$opt_vardir/run/mysqld_2.pid",
1283   nonguarded   => 1,
1284   start_timeout  => 400, # enough time create innodb tables
1285   old_log_format => 1
1286  };
1287
1288  my $data_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port";
1289  $clusters->[0]=
1290  {
1291   name            => "Master",
1292   nodes           => 2,
1293   port            => "$opt_ndbcluster_port",
1294   data_dir        => "$data_dir",
1295   connect_string  => "host=localhost:$opt_ndbcluster_port",
1296   path_pid        => "$data_dir/ndb_3.pid", # Nodes + 1
1297   pid             => 0, # pid of ndb_mgmd
1298   installed_ok    => 0,
1299  };
1300
1301  $data_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port_slave";
1302  $clusters->[1]=
1303  {
1304   name            => "Slave",
1305   nodes           => 1,
1306   port            => "$opt_ndbcluster_port_slave",
1307   data_dir        => "$data_dir",
1308   connect_string  => "host=localhost:$opt_ndbcluster_port_slave",
1309   path_pid        => "$data_dir/ndb_2.pid", # Nodes + 1
1310   pid             => 0, # pid of ndb_mgmd
1311   installed_ok    => 0,
1312  };
1313
1314  # Init pids of ndbd's
1315  foreach my $cluster ( @{$clusters} )
1316  {
1317    for ( my $idx= 0; $idx < $cluster->{'nodes'}; $idx++ )
1318    {
1319      my $nodeid= $idx+1;
1320      $cluster->{'ndbds'}->[$idx]=
1321	{
1322	 pid      => 0,
1323	 nodeid => $nodeid,
1324	 path_pid => "$cluster->{'data_dir'}/ndb_${nodeid}.pid",
1325	 path_fs => "$cluster->{'data_dir'}/ndb_${nodeid}_fs",
1326	};
1327    }
1328  }
1329
1330  # --------------------------------------------------------------------------
1331  # extern
1332  # --------------------------------------------------------------------------
1333  if ( $opt_extern )
1334  {
1335    # Turn off features not supported when running with extern server
1336    $opt_skip_rpl= 1;
1337    $opt_skip_ndbcluster= 1;
1338
1339    # Setup master->[0] with the settings for the extern server
1340    $master->[0]->{'path_sock'}=  $opt_socket ? $opt_socket : "/tmp/mysql.sock";
1341    mtr_report("Using extern server at '$master->[0]->{path_sock}'");
1342  }
1343  else
1344  {
1345    mtr_error("--socket can only be used in combination with --extern")
1346      if $opt_socket;
1347  }
1348
1349
1350  # --------------------------------------------------------------------------
1351  # ndbconnectstring and ndbconnectstring_slave
1352  # --------------------------------------------------------------------------
1353  if ( $opt_ndbconnectstring )
1354  {
1355    # ndbconnectstring was supplied by user, the tests shoudl be run
1356    # against an already started cluster, change settings
1357    my $cluster= $clusters->[0]; # Master cluster
1358    $cluster->{'connect_string'}= $opt_ndbconnectstring;
1359    $cluster->{'use_running'}= 1;
1360
1361    mtr_error("Can't specify --ndb-connectstring and --skip-ndbcluster")
1362      if $opt_skip_ndbcluster;
1363  }
1364  $ENV{'NDB_CONNECTSTRING'}= $clusters->[0]->{'connect_string'};
1365
1366
1367  if ( $opt_ndbconnectstring_slave )
1368  {
1369    # ndbconnectstring-slave was supplied by user, the tests should be run
1370    # agains an already started slave cluster, change settings
1371    my $cluster= $clusters->[1]; # Slave cluster
1372    $cluster->{'connect_string'}= $opt_ndbconnectstring_slave;
1373    $cluster->{'use_running'}= 1;
1374
1375    mtr_error("Can't specify ndb-connectstring_slave and " .
1376	      "--skip-ndbcluster-slave")
1377      if $opt_skip_ndbcluster_slave;
1378  }
1379
1380
1381  $path_timefile=  "$opt_vardir/log/mysqltest-time";
1382  $path_mysqltest_log=  "$opt_vardir/log/mysqltest.log";
1383  $path_current_test_log= "$opt_vardir/log/current_test";
1384  $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
1385
1386  $path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/";
1387
1388  if ( $opt_valgrind and $opt_debug )
1389  {
1390    # When both --valgrind and --debug is selected, send
1391    # all output to the trace file, making it possible to
1392    # see the exact location where valgrind complains
1393    foreach my $mysqld (@{$master}, @{$slave})
1394    {
1395      my $sidx= $mysqld->{idx} ? "$mysqld->{idx}" : "";
1396      $mysqld->{path_myerr}=
1397	"$opt_vardir/log/" . $mysqld->{type} . "$sidx.trace";
1398    }
1399  }
1400}
1401
1402#
1403# To make it easier for different devs to work on the same host,
1404# an environment variable can be used to control all ports. A small
1405# number is to be used, 0 - 16 or similar.
1406#
1407# Note the MASTER_MYPORT has to be set the same in all 4.x and 5.x
1408# versions of this script, else a 4.0 test run might conflict with a
1409# 5.1 test run, even if different MTR_BUILD_THREAD is used. This means
1410# all port numbers might not be used in this version of the script.
1411#
1412# Also note the limitation of ports we are allowed to hand out. This
1413# differs between operating systems and configuration, see
1414# http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html
1415# But a fairly safe range seems to be 5001 - 32767
1416#
1417
1418sub set_mtr_build_thread_ports($) {
1419  my $mtr_build_thread= shift;
1420
1421  if ( lc($mtr_build_thread) eq 'auto' ) {
1422    print "Requesting build thread... ";
1423    $ENV{'MTR_BUILD_THREAD'} = $mtr_build_thread = mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299);
1424    print "got ".$mtr_build_thread."\n";
1425  }
1426
1427  # Up to two masters, up to three slaves
1428  # A magic value in command_line_setup depends on these equations.
1429  $opt_master_myport=         $mtr_build_thread * 10 + 10000; # and 1
1430  $opt_slave_myport=          $opt_master_myport + 2;  # and 3 4
1431  $opt_ndbcluster_port=       $opt_master_myport + 5;
1432  $opt_ndbcluster_port_slave= $opt_master_myport + 6;
1433  $im_port=                   $opt_master_myport + 7;
1434  $im_mysqld1_port=           $opt_master_myport + 8;
1435  $im_mysqld2_port=           $opt_master_myport + 9;
1436
1437  if ( $opt_master_myport < 5001 or $opt_master_myport + 10 >= 32767 )
1438  {
1439    mtr_error("MTR_BUILD_THREAD number results in a port",
1440              "outside 5001 - 32767",
1441              "($opt_master_myport - $opt_master_myport + 10)");
1442  }
1443}
1444
1445
1446sub datadir_list_setup () {
1447
1448  # Make a list of all data_dirs
1449  for (my $idx= 0; $idx < $max_master_num; $idx++)
1450  {
1451    push(@data_dir_lst, $master->[$idx]->{'path_myddir'});
1452  }
1453
1454  for (my $idx= 0; $idx < $max_slave_num; $idx++)
1455  {
1456    push(@data_dir_lst, $slave->[$idx]->{'path_myddir'});
1457  }
1458
1459  unless ($opt_skip_im)
1460  {
1461    foreach my $instance (@{$instance_manager->{'instances'}})
1462    {
1463      push(@data_dir_lst, $instance->{'path_datadir'});
1464    }
1465  }
1466}
1467
1468
1469##############################################################################
1470#
1471#  Set paths to various executable programs
1472#
1473##############################################################################
1474
1475
1476sub collect_mysqld_features () {
1477  my $found_variable_list_start= 0;
1478  my $tmpdir;
1479  if ( $opt_tmpdir ) {
1480    # Use the requested tmpdir
1481    mkpath($opt_tmpdir) if (! -d $opt_tmpdir);
1482    $tmpdir= $opt_tmpdir;
1483  }
1484  else {
1485    $tmpdir= tempdir(CLEANUP => 0); # Directory removed by this function
1486  }
1487
1488  #
1489  # Execute "mysqld --help --verbose" to get a list
1490  # list of all features and settings
1491  #
1492  # --no-defaults and --skip-grant-tables are to avoid loading
1493  # system-wide configs and plugins
1494  #
1495  # --datadir must exist, mysqld will chdir into it
1496  #
1497  my $list= `$exe_mysqld --no-defaults --datadir=$tmpdir --lc-messages-dir=$path_language --skip-grant-tables --verbose --help`;
1498
1499  foreach my $line (split('\n', $list))
1500  {
1501    # First look for version
1502    if ( !$mysql_version_id )
1503    {
1504      # Look for version
1505      my $exe_name= basename($exe_mysqld);
1506      mtr_verbose("exe_name: $exe_name");
1507      if ( $line =~ /^\S*$exe_name\s\sVer\s([0-9]*)\.([0-9]*)\.([0-9]*)/ )
1508      {
1509	#print "Major: $1 Minor: $2 Build: $3\n";
1510	$mysql_version_id= $1*10000 + $2*100 + $3;
1511	#print "mysql_version_id: $mysql_version_id\n";
1512	mtr_report("MySQL Version $1.$2.$3");
1513      }
1514    }
1515    else
1516    {
1517      if (!$found_variable_list_start)
1518      {
1519	# Look for start of variables list
1520	if ( $line =~ /[\-]+\s[\-]+/ )
1521	{
1522	  $found_variable_list_start= 1;
1523	}
1524      }
1525      else
1526      {
1527	# Put variables into hash
1528	if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ )
1529	{
1530	  # print "$1=\"$2\"\n";
1531	  $mysqld_variables{$1}= $2;
1532	}
1533	else
1534	{
1535	  # The variable list is ended with a blank line
1536	  if ( $line =~ /^[\s]*$/ )
1537	  {
1538	    last;
1539	  }
1540	  else
1541	  {
1542	    # Send out a warning, we should fix the variables that has no
1543	    # space between variable name and it's value
1544	    # or should it be fixed width column parsing? It does not
1545	    # look like that in function my_print_variables in my_getopt.c
1546	    mtr_warning("Could not parse variable list line : $line");
1547	  }
1548	}
1549      }
1550    }
1551  }
1552  rmtree($tmpdir) if (!$opt_tmpdir);
1553  mtr_error("Could not find version of MySQL") unless $mysql_version_id;
1554  mtr_error("Could not find variabes list") unless $found_variable_list_start;
1555
1556}
1557
1558
1559sub run_query($$) {
1560  my ($mysqld, $query)= @_;
1561
1562  my $args;
1563  mtr_init_args(\$args);
1564
1565  mtr_add_arg($args, "--no-defaults");
1566  mtr_add_arg($args, "--user=%s", $opt_user);
1567  mtr_add_arg($args, "--port=%d", $mysqld->{'port'});
1568  mtr_add_arg($args, "--socket=%s", $mysqld->{'path_sock'});
1569  mtr_add_arg($args, "--silent"); # Tab separated output
1570  mtr_add_arg($args, "-e '%s'", $query);
1571
1572  my $cmd= "$exe_mysql " . join(' ', @$args);
1573  mtr_verbose("cmd: $cmd");
1574  return `$cmd`;
1575}
1576
1577
1578sub collect_mysqld_features_from_running_server ()
1579{
1580  my $list= run_query($master->[0], "use mysql; SHOW VARIABLES");
1581
1582  foreach my $line (split('\n', $list))
1583  {
1584    # Put variables into hash
1585    if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ )
1586    {
1587      print "$1=\"$2\"\n";
1588      $mysqld_variables{$1}= $2;
1589    }
1590  }
1591}
1592
1593sub executable_setup_ndb () {
1594
1595  # Look for ndb tols and binaries
1596  my $ndb_path= mtr_file_exists("$glob_bindir/ndb",
1597				"$glob_bindir/storage/ndb",
1598				"$glob_bindir/bin");
1599
1600  $exe_ndbd=
1601    mtr_exe_maybe_exists("$ndb_path/src/kernel/ndbd",
1602			 "$ndb_path/ndbd",
1603			 "$glob_bindir/libexec/ndbd");
1604  $exe_ndb_mgm=
1605    mtr_exe_maybe_exists("$ndb_path/src/mgmclient/ndb_mgm",
1606			 "$ndb_path/ndb_mgm");
1607  $exe_ndb_mgmd=
1608    mtr_exe_maybe_exists("$ndb_path/src/mgmsrv/ndb_mgmd",
1609			 "$ndb_path/ndb_mgmd",
1610			 "$glob_bindir/libexec/ndb_mgmd");
1611  $exe_ndb_waiter=
1612    mtr_exe_maybe_exists("$ndb_path/tools/ndb_waiter",
1613			 "$ndb_path/ndb_waiter");
1614
1615  # May not exist
1616  $path_ndb_tools_dir= mtr_file_exists("$ndb_path/tools",
1617				       "$ndb_path");
1618  # May not exist
1619  $path_ndb_examples_dir=
1620    mtr_file_exists("$ndb_path/ndbapi-examples",
1621		    "$ndb_path/examples");
1622  # May not exist
1623  $exe_ndb_example=
1624    mtr_file_exists("$path_ndb_examples_dir/ndbapi_simple/ndbapi_simple");
1625
1626  return ( $exe_ndbd eq "" or
1627	   $exe_ndb_mgm eq "" or
1628	   $exe_ndb_mgmd eq "" or
1629	   $exe_ndb_waiter eq "");
1630}
1631
1632sub executable_setup () {
1633
1634  #
1635  # Check if libtool is available in this distribution/clone
1636  # we need it when valgrinding or debugging non installed binary
1637  # Otherwise valgrind will valgrind the libtool wrapper or bash
1638  # and gdb will not find the real executable to debug
1639  #
1640  if ( -x "../libtool")
1641  {
1642    $exe_libtool= "../libtool";
1643    if ($opt_valgrind or $glob_debugger)
1644    {
1645      mtr_report("Using \"$exe_libtool\" when running valgrind or debugger");
1646    }
1647  }
1648
1649  # Look for my_print_defaults
1650  $exe_my_print_defaults=
1651    mtr_exe_exists(vs_config_dirs('extra', 'my_print_defaults'),
1652		           "$path_client_bindir/my_print_defaults",
1653		           "$glob_bindir/extra/my_print_defaults");
1654
1655  # Look for perror
1656  $exe_perror= mtr_exe_exists(vs_config_dirs('extra', 'perror'),
1657			                  "$glob_bindir/extra/perror",
1658			                  "$path_client_bindir/perror");
1659
1660  # Look for the client binaries
1661  $exe_mysqlcheck=     mtr_exe_exists("$path_client_bindir/mysqlcheck");
1662  $exe_mysqldump=      mtr_exe_exists("$path_client_bindir/mysqldump");
1663  $exe_mysqlimport=    mtr_exe_exists("$path_client_bindir/mysqlimport");
1664  $exe_mysqlshow=      mtr_exe_exists("$path_client_bindir/mysqlshow");
1665  $exe_mysqlbinlog=    mtr_exe_exists("$path_client_bindir/mysqlbinlog");
1666  $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
1667  $exe_mysql=          mtr_exe_exists("$path_client_bindir/mysql");
1668  $exe_mysql_config_editor=
1669                       mtr_exe_exists("$path_client_bindir/mysql_config_editor");
1670
1671  if (!$opt_extern)
1672  {
1673    # Look for SQL scripts directory
1674    if ( mtr_file_exists("$path_share/mysql_system_tables.sql") ne "")
1675    {
1676      # The SQL scripts are in path_share
1677      $path_sql_dir= $path_share;
1678    }
1679    else
1680    {
1681      $path_sql_dir= mtr_path_exists("$glob_basedir/share",
1682				     "$glob_basedir/scripts");
1683    }
1684
1685    if ( $mysql_version_id >= 50100 )
1686    {
1687      $exe_mysqlslap=    mtr_exe_exists("$path_client_bindir/mysqlslap");
1688    }
1689    if ( $mysql_version_id >= 50000 and !$glob_use_embedded_server )
1690    {
1691      $exe_mysql_upgrade= mtr_exe_exists("$path_client_bindir/mysql_upgrade")
1692    }
1693    else
1694    {
1695      $exe_mysql_upgrade= "";
1696    }
1697
1698    # Look for mysql_fix_privilege_tables.sql script
1699    $file_mysql_fix_privilege_tables=
1700      mtr_file_exists("$glob_basedir/scripts/mysql_fix_privilege_tables.sql",
1701  		    "$glob_basedir/share/mysql_fix_privilege_tables.sql",
1702  		    "$glob_basedir/share/mysql/mysql_fix_privilege_tables.sql");
1703
1704    if ( ! $opt_skip_ndbcluster and executable_setup_ndb())
1705    {
1706      mtr_warning("Could not find all required ndb binaries, " .
1707  		"all ndb tests will fail, use --skip-ndbcluster to " .
1708  		"skip testing it.");
1709
1710      foreach my $cluster (@{$clusters})
1711      {
1712        $cluster->{"executable_setup_failed"}= 1;
1713      }
1714    }
1715
1716    # Look for the udf_example library
1717    $lib_udf_example=
1718      mtr_file_exists(vs_config_dirs('sql', 'udf_example.dll'),
1719                      "$glob_bindir/sql/.libs/udf_example.so",);
1720
1721    # Look for the ha_example library
1722    $lib_example_plugin=
1723      mtr_file_exists(vs_config_dirs('storage/example', 'ha_example.dll'),
1724                      "$glob_bindir/storage/example/.libs/ha_example.so",);
1725
1726  }
1727
1728  # Look for mysqltest executable
1729  if ( $glob_use_embedded_server )
1730  {
1731    $exe_mysqltest=
1732      mtr_exe_exists(vs_config_dirs('libmysqld/examples','mysqltest_embedded'),
1733                     "$glob_bindir/libmysqld/examples/mysqltest_embedded",
1734                     "$path_client_bindir/mysqltest_embedded");
1735  }
1736  else
1737  {
1738    $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
1739  }
1740
1741  # Look for mysql_client_test executable which may _not_ exist in
1742  # some versions, test using it should be skipped
1743  if ( $glob_use_embedded_server )
1744  {
1745    $exe_mysql_client_test=
1746      mtr_exe_maybe_exists(
1747        vs_config_dirs('libmysqld/examples', 'mysql_client_test_embedded'),
1748        "$glob_bindir/libmysqld/examples/mysql_client_test_embedded");
1749  }
1750  else
1751  {
1752    $exe_mysql_client_test=
1753      mtr_exe_maybe_exists(vs_config_dirs('tests', 'mysql_client_test'),
1754                           "$glob_bindir/tests/mysql_client_test",
1755                           "$glob_bindir/bin/mysql_client_test");
1756  }
1757
1758  # Look for bug25714 executable which may _not_ exist in
1759  # some versions, test using it should be skipped
1760  $exe_bug25714=
1761      mtr_exe_maybe_exists(vs_config_dirs('tests', 'bug25714'),
1762                           "$glob_bindir/tests/bug25714");
1763}
1764
1765
1766sub generate_cmdline_mysqldump ($) {
1767  my($mysqld) = @_;
1768  return
1769    mtr_native_path($exe_mysqldump) .
1770      " --no-defaults -uroot --debug-check " .
1771      "--port=$mysqld->{'port'} " .
1772      "--socket=$mysqld->{'path_sock'} --password=";
1773}
1774
1775
1776##############################################################################
1777#
1778#  Set environment to be used by childs of this process for
1779#  things that are constant duting the whole lifetime of mysql-test-run.pl
1780#
1781##############################################################################
1782
1783sub mysql_client_test_arguments()
1784{
1785  my $exe= $exe_mysql_client_test;
1786
1787  my $args;
1788  mtr_init_args(\$args);
1789  if ( $opt_valgrind_mysqltest )
1790  {
1791    valgrind_arguments($args, \$exe);
1792  }
1793
1794  mtr_add_arg($args, "--no-defaults");
1795  mtr_add_arg($args, "--testcase");
1796  mtr_add_arg($args, "--user=root");
1797  mtr_add_arg($args, "--port=$master->[0]->{'port'}");
1798  mtr_add_arg($args, "--socket=$master->[0]->{'path_sock'}");
1799
1800  if ( $opt_extern || $mysql_version_id >= 50000 )
1801  {
1802    mtr_add_arg($args, "--vardir=$opt_vardir")
1803  }
1804
1805  if ( $opt_debug )
1806  {
1807    mtr_add_arg($args,
1808      "--debug=d:t:A,$path_vardir_trace/log/mysql_client_test.trace");
1809  }
1810
1811  if ( $glob_use_embedded_server )
1812  {
1813    mtr_add_arg($args,
1814      " -A --lc-messages-dir=$path_language");
1815    mtr_add_arg($args,
1816      " -A --datadir=$slave->[0]->{'path_myddir'}");
1817    mtr_add_arg($args,
1818      " -A --character-sets-dir=$path_charsetsdir");
1819  }
1820
1821  return join(" ", $exe, @$args);
1822}
1823
1824sub mysql_upgrade_arguments()
1825{
1826  my $exe= $exe_mysql_upgrade;
1827
1828  my $args;
1829  mtr_init_args(\$args);
1830#  if ( $opt_valgrind_mysql_ugrade )
1831#  {
1832#    valgrind_arguments($args, \$exe);
1833#  }
1834
1835  mtr_add_arg($args, "--no-defaults");
1836  mtr_add_arg($args, "--user=root");
1837  mtr_add_arg($args, "--port=$master->[0]->{'port'}");
1838  mtr_add_arg($args, "--socket=$master->[0]->{'path_sock'}");
1839  mtr_add_arg($args, "--datadir=$master->[0]->{'path_myddir'}");
1840  mtr_add_arg($args, "--basedir=$glob_basedir");
1841  mtr_add_arg($args, "--tmpdir=$opt_tmpdir");
1842
1843  if ( $opt_debug )
1844  {
1845    mtr_add_arg($args,
1846      "--debug=d:t:A,$path_vardir_trace/log/mysql_upgrade.trace");
1847  }
1848
1849  return join(" ", $exe, @$args);
1850}
1851
1852# Note that some env is setup in spawn/run, in "mtr_process.pl"
1853
1854sub environment_setup () {
1855
1856  umask(022);
1857
1858  my @ld_library_paths;
1859
1860  if ($path_client_libdir)
1861  {
1862    # Use the --client-libdir passed on commandline
1863    push(@ld_library_paths, "$path_client_libdir");
1864  }
1865  else
1866  {
1867    # Setup LD_LIBRARY_PATH so the libraries from this distro/clone
1868    # are used in favor of the system installed ones
1869    if ( $source_dist )
1870    {
1871      push(@ld_library_paths, "$glob_bindir/libmysql/.libs/",
1872	   "$glob_bindir/libmysql_r/.libs/",
1873	   "$glob_bindir/zlib.libs/");
1874    }
1875    else
1876    {
1877      push(@ld_library_paths, "$glob_bindir/lib");
1878    }
1879  }
1880
1881 # --------------------------------------------------------------------------
1882  # Add the path where libndbclient can be found
1883  # --------------------------------------------------------------------------
1884  if ( $glob_ndbcluster_supported )
1885  {
1886    push(@ld_library_paths,  "$glob_bindir/storage/ndb/src/.libs");
1887  }
1888
1889  # --------------------------------------------------------------------------
1890  # Valgrind need to be run with debug libraries otherwise it's almost
1891  # impossible to add correct supressions, that means if "/usr/lib/debug"
1892  # is available, it should be added to
1893  # LD_LIBRARY_PATH
1894  #
1895  # But pthread is broken in libc6-dbg on Debian <= 3.1 (see Debian
1896  # bug 399035, http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=399035),
1897  # so don't change LD_LIBRARY_PATH on that platform.
1898  # --------------------------------------------------------------------------
1899  my $debug_libraries_path= "/usr/lib/debug";
1900  my $deb_version;
1901  if (  $opt_valgrind and -d $debug_libraries_path and
1902        (! -e '/etc/debian_version' or
1903	 ($deb_version= mtr_grab_file('/etc/debian_version')) !~ /^[0-9]+\.[0-9]$/ or
1904         $deb_version > 3.1 ) )
1905  {
1906    push(@ld_library_paths, $debug_libraries_path);
1907  }
1908
1909  $ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths,
1910				$ENV{'LD_LIBRARY_PATH'} ?
1911				split(':', $ENV{'LD_LIBRARY_PATH'}) : ());
1912  mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}");
1913
1914  $ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths,
1915				  $ENV{'DYLD_LIBRARY_PATH'} ?
1916				  split(':', $ENV{'DYLD_LIBRARY_PATH'}) : ());
1917  mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}");
1918
1919  # The environment variable used for shared libs on AIX
1920  $ENV{'SHLIB_PATH'}= join(":", @ld_library_paths,
1921                           $ENV{'SHLIB_PATH'} ?
1922                           split(':', $ENV{'SHLIB_PATH'}) : ());
1923  mtr_debug("SHLIB_PATH: $ENV{'SHLIB_PATH'}");
1924
1925  # The environment variable used for shared libs on hp-ux
1926  $ENV{'LIBPATH'}= join(":", @ld_library_paths,
1927                        $ENV{'LIBPATH'} ?
1928                        split(':', $ENV{'LIBPATH'}) : ());
1929  mtr_debug("LIBPATH: $ENV{'LIBPATH'}");
1930
1931  # --------------------------------------------------------------------------
1932  # Also command lines in .opt files may contain env vars
1933  # --------------------------------------------------------------------------
1934
1935  $ENV{'CHARSETSDIR'}=              $path_charsetsdir;
1936  $ENV{'UMASK'}=              "0660"; # The octal *string*
1937  $ENV{'UMASK_DIR'}=          "0770"; # The octal *string*
1938
1939  #
1940  # MySQL tests can produce output in various character sets
1941  # (especially, ctype_xxx.test). To avoid confusing Perl
1942  # with output which is incompatible with the current locale
1943  # settings, we reset the current values of LC_ALL and LC_CTYPE to "C".
1944  # For details, please see
1945  # Bug#27636 tests fails if LC_* variables set to *_*.UTF-8
1946  #
1947  $ENV{'LC_ALL'}=             "C";
1948  $ENV{'LC_CTYPE'}=           "C";
1949
1950  $ENV{'LC_COLLATE'}=         "C";
1951  $ENV{'USE_RUNNING_SERVER'}= $opt_extern;
1952  $ENV{'MYSQL_TEST_DIR'}=     $glob_mysql_test_dir;
1953  $ENV{'MYSQLTEST_VARDIR'}=   $opt_vardir;
1954  $ENV{'MYSQL_TMP_DIR'}=      $opt_tmpdir;
1955  $ENV{'MASTER_MYSOCK'}=      $master->[0]->{'path_sock'};
1956  $ENV{'MASTER_MYSOCK1'}=     $master->[1]->{'path_sock'};
1957  $ENV{'MASTER_MYPORT'}=      $master->[0]->{'port'};
1958  $ENV{'MASTER_MYPORT1'}=     $master->[1]->{'port'};
1959  $ENV{'SLAVE_MYSOCK'}=       $slave->[0]->{'path_sock'};
1960  $ENV{'SLAVE_MYPORT'}=       $slave->[0]->{'port'};
1961  $ENV{'SLAVE_MYPORT1'}=      $slave->[1]->{'port'};
1962  $ENV{'SLAVE_MYPORT2'}=      $slave->[2]->{'port'};
1963  $ENV{'MYSQL_TCP_PORT'}=     $mysqld_variables{'port'};
1964  $ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'master-port'};
1965
1966  $ENV{'IM_PATH_SOCK'}=       $instance_manager->{path_sock};
1967  $ENV{'IM_USERNAME'}=        $instance_manager->{admin_login};
1968  $ENV{'IM_PASSWORD'}=        $instance_manager->{admin_password};
1969  $ENV{MTR_BUILD_THREAD}=      $opt_mtr_build_thread;
1970
1971  $ENV{'EXE_MYSQL'}=          $exe_mysql;
1972
1973
1974  # ----------------------------------------------------
1975  # Setup env for NDB
1976  # ----------------------------------------------------
1977  if ( ! $opt_skip_ndbcluster )
1978  {
1979    $ENV{'NDB_MGM'}=                  $exe_ndb_mgm;
1980
1981    $ENV{'NDBCLUSTER_PORT'}=          $opt_ndbcluster_port;
1982    $ENV{'NDBCLUSTER_PORT_SLAVE'}=    $opt_ndbcluster_port_slave;
1983
1984    $ENV{'NDB_EXTRA_TEST'}=           $opt_ndb_extra_test;
1985
1986    $ENV{'NDB_BACKUP_DIR'}=           $clusters->[0]->{'data_dir'};
1987    $ENV{'NDB_DATA_DIR'}=             $clusters->[0]->{'data_dir'};
1988    $ENV{'NDB_TOOLS_DIR'}=            $path_ndb_tools_dir;
1989    $ENV{'NDB_TOOLS_OUTPUT'}=         $path_ndb_testrun_log;
1990
1991    if ( $mysql_version_id >= 50000 )
1992    {
1993      $ENV{'NDB_EXAMPLES_DIR'}=         $path_ndb_examples_dir;
1994      $ENV{'MY_NDB_EXAMPLES_BINARY'}=   $exe_ndb_example;
1995    }
1996    $ENV{'NDB_EXAMPLES_OUTPUT'}=      $path_ndb_testrun_log;
1997  }
1998
1999  # ----------------------------------------------------
2000  # Setup env for IM
2001  # ----------------------------------------------------
2002  if ( ! $opt_skip_im )
2003  {
2004    $ENV{'IM_PATH_PID'}=        $instance_manager->{path_pid};
2005    $ENV{'IM_PATH_ANGEL_PID'}=  $instance_manager->{path_angel_pid};
2006    $ENV{'IM_PORT'}=            $instance_manager->{port};
2007    $ENV{'IM_DEFAULTS_PATH'}=   $instance_manager->{defaults_file};
2008    $ENV{'IM_PASSWORD_PATH'}=   $instance_manager->{password_file};
2009
2010    $ENV{'IM_MYSQLD1_SOCK'}=
2011      $instance_manager->{instances}->[0]->{path_sock};
2012    $ENV{'IM_MYSQLD1_PORT'}=
2013      $instance_manager->{instances}->[0]->{port};
2014    $ENV{'IM_MYSQLD1_PATH_PID'}=
2015      $instance_manager->{instances}->[0]->{path_pid};
2016    $ENV{'IM_MYSQLD2_SOCK'}=
2017      $instance_manager->{instances}->[1]->{path_sock};
2018    $ENV{'IM_MYSQLD2_PORT'}=
2019      $instance_manager->{instances}->[1]->{port};
2020    $ENV{'IM_MYSQLD2_PATH_PID'}=
2021      $instance_manager->{instances}->[1]->{path_pid};
2022  }
2023
2024  # ----------------------------------------------------
2025  # Setup env so childs can execute mysqlcheck
2026  # ----------------------------------------------------
2027  my $cmdline_mysqlcheck=
2028    mtr_native_path($exe_mysqlcheck) .
2029    " --no-defaults --debug-check -uroot " .
2030    "--port=$master->[0]->{'port'} " .
2031    "--socket=$master->[0]->{'path_sock'} --password=";
2032
2033  if ( $opt_debug )
2034  {
2035    $cmdline_mysqlcheck .=
2036      " --debug=d:t:A,$path_vardir_trace/log/mysqlcheck.trace";
2037  }
2038  $ENV{'MYSQL_CHECK'}=              $cmdline_mysqlcheck;
2039
2040  # ----------------------------------------------------
2041  # Setup env to childs can execute myqldump
2042  # ----------------------------------------------------
2043  my $cmdline_mysqldump= generate_cmdline_mysqldump($master->[0]);
2044  my $cmdline_mysqldumpslave= generate_cmdline_mysqldump($slave->[0]);
2045
2046  if ( $opt_debug )
2047  {
2048    $cmdline_mysqldump .=
2049      " --debug=d:t:A,$path_vardir_trace/log/mysqldump-master.trace";
2050    $cmdline_mysqldumpslave .=
2051      " --debug=d:t:A,$path_vardir_trace/log/mysqldump-slave.trace";
2052  }
2053  $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
2054  $ENV{'MYSQL_DUMP_SLAVE'}= $cmdline_mysqldumpslave;
2055
2056
2057  # ----------------------------------------------------
2058  # Setup env so childs can execute mysqlslap
2059  # ----------------------------------------------------
2060  if ( $exe_mysqlslap )
2061  {
2062    my $cmdline_mysqlslap=
2063      mtr_native_path($exe_mysqlslap) .
2064      " -uroot " .
2065      "--port=$master->[0]->{'port'} " .
2066      "--socket=$master->[0]->{'path_sock'} --password= ";
2067
2068    if ( $opt_debug )
2069   {
2070      $cmdline_mysqlslap .=
2071	" --debug=d:t:A,$path_vardir_trace/log/mysqlslap.trace";
2072    }
2073    $ENV{'MYSQL_SLAP'}= $cmdline_mysqlslap;
2074  }
2075
2076  # ----------------------------------------------------
2077  # Setup env so childs can execute mysqlimport
2078  # ----------------------------------------------------
2079  my $cmdline_mysqlimport=
2080    mtr_native_path($exe_mysqlimport) .
2081    " -uroot --debug-check " .
2082    "--port=$master->[0]->{'port'} " .
2083    "--socket=$master->[0]->{'path_sock'} --password=";
2084
2085  if ( $opt_debug )
2086  {
2087    $cmdline_mysqlimport .=
2088      " --debug=d:t:A,$path_vardir_trace/log/mysqlimport.trace";
2089  }
2090  $ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport;
2091
2092
2093  # ----------------------------------------------------
2094  # Setup env so childs can execute mysqlshow
2095  # ----------------------------------------------------
2096  my $cmdline_mysqlshow=
2097    mtr_native_path($exe_mysqlshow) .
2098    " -uroot --debug-check " .
2099    "--port=$master->[0]->{'port'} " .
2100    "--socket=$master->[0]->{'path_sock'} --password=";
2101
2102  if ( $opt_debug )
2103  {
2104    $cmdline_mysqlshow .=
2105      " --debug=d:t:A,$path_vardir_trace/log/mysqlshow.trace";
2106  }
2107  $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
2108
2109  # ----------------------------------------------------
2110  # Setup env so childs can execute mysql_config_editor
2111  # ----------------------------------------------------
2112  my $cmdline_mysql_config_editor=
2113    mtr_native_path($exe_mysql_config_editor) . " ";
2114
2115  if ( $opt_debug )
2116  {
2117    $cmdline_mysql_config_editor .=
2118      " --debug=d:t:A,$path_vardir_trace/log/mysql_config_editor.trace";
2119  }
2120  $ENV{'MYSQL_CONFIG_EDITOR'}= $cmdline_mysql_config_editor;
2121
2122
2123  # ----------------------------------------------------
2124  # Setup env so childs can execute mysqlbinlog
2125  # ----------------------------------------------------
2126  my $cmdline_mysqlbinlog=
2127    mtr_native_path($exe_mysqlbinlog) .
2128      " --no-defaults --disable-force-if-open --debug-check";
2129  if ( !$opt_extern && $mysql_version_id >= 50000 )
2130  {
2131    $cmdline_mysqlbinlog .=" --character-sets-dir=$path_charsetsdir";
2132  }
2133  # Always use the given tmpdir for the LOAD files created
2134  # by mysqlbinlog
2135  $cmdline_mysqlbinlog .=" --local-load=$opt_tmpdir";
2136
2137  if ( $opt_debug )
2138  {
2139    $cmdline_mysqlbinlog .=
2140      " --debug=d:t:A,$path_vardir_trace/log/mysqlbinlog.trace";
2141  }
2142  $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
2143
2144  # ----------------------------------------------------
2145  # Setup env so childs can execute mysql
2146  # ----------------------------------------------------
2147  my $cmdline_mysql=
2148    mtr_native_path($exe_mysql) .
2149    " --no-defaults --debug-check --host=localhost  --user=root --password= " .
2150    "--port=$master->[0]->{'port'} " .
2151    "--socket=$master->[0]->{'path_sock'} ".
2152    "--character-sets-dir=$path_charsetsdir";
2153
2154  $ENV{'MYSQL'}= $cmdline_mysql;
2155
2156  # ----------------------------------------------------
2157  # Setup env so childs can execute bug25714
2158  # ----------------------------------------------------
2159  $ENV{'MYSQL_BUG25714'}=  $exe_bug25714;
2160
2161  # ----------------------------------------------------
2162  # Setup env so childs can execute mysql_client_test
2163  # ----------------------------------------------------
2164  $ENV{'MYSQL_CLIENT_TEST'}=  mysql_client_test_arguments();
2165
2166  # ----------------------------------------------------
2167  # Setup env so childs can execute mysql_upgrade
2168  # ----------------------------------------------------
2169  if ( !$opt_extern && $mysql_version_id >= 50000 )
2170  {
2171    $ENV{'MYSQL_UPGRADE'}= mysql_upgrade_arguments();
2172  }
2173
2174  $ENV{'MYSQL_FIX_PRIVILEGE_TABLES'}=  $file_mysql_fix_privilege_tables;
2175
2176  # ----------------------------------------------------
2177  # Setup env so childs can execute my_print_defaults
2178  # ----------------------------------------------------
2179  $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= mtr_native_path($exe_my_print_defaults);
2180
2181  # ----------------------------------------------------
2182  # Setup env so childs can execute mysqladmin
2183  # ----------------------------------------------------
2184  $ENV{'MYSQLADMIN'}= mtr_native_path($exe_mysqladmin);
2185
2186  # ----------------------------------------------------
2187  # Setup env so childs can execute perror
2188  # ----------------------------------------------------
2189  $ENV{'MY_PERROR'}= mtr_native_path($exe_perror);
2190
2191  # ----------------------------------------------------
2192  # Add the path where mysqld will find udf_example.so
2193  # ----------------------------------------------------
2194  $ENV{'UDF_EXAMPLE_LIB'}=
2195    ($lib_udf_example ? basename($lib_udf_example) : "");
2196  $ENV{'UDF_EXAMPLE_LIB_OPT'}=
2197    ($lib_udf_example ? "--plugin_dir=" . dirname($lib_udf_example) : "");
2198
2199  # ----------------------------------------------------
2200  # Add the path where mysqld will find ha_example.so
2201  # ----------------------------------------------------
2202  $ENV{'EXAMPLE_PLUGIN'}=
2203    ($lib_example_plugin ? basename($lib_example_plugin) : "");
2204  $ENV{'EXAMPLE_PLUGIN_OPT'}=
2205    ($lib_example_plugin ? "--plugin_dir=" . dirname($lib_example_plugin) : "");
2206
2207  # ----------------------------------------------------
2208  # Setup env so childs can execute myisampack and myisamchk
2209  # ----------------------------------------------------
2210  $ENV{'MYISAMCHK'}= mtr_native_path(mtr_exe_exists(
2211                       vs_config_dirs('storage/myisam', 'myisamchk'),
2212                       vs_config_dirs('myisam', 'myisamchk'),
2213                       "$path_client_bindir/myisamchk",
2214                       "$glob_bindir/storage/myisam/myisamchk",
2215                       "$glob_bindir/myisam/myisamchk"));
2216  $ENV{'MYISAMPACK'}= mtr_native_path(mtr_exe_exists(
2217                        vs_config_dirs('storage/myisam', 'myisampack'),
2218                        vs_config_dirs('myisam', 'myisampack'),
2219                        "$path_client_bindir/myisampack",
2220                        "$glob_bindir/storage/myisam/myisampack",
2221                        "$glob_bindir/myisam/myisampack"));
2222
2223  # ----------------------------------------------------
2224  # We are nice and report a bit about our settings
2225  # ----------------------------------------------------
2226  if (!$opt_extern)
2227  {
2228    print "Using MTR_BUILD_THREAD      = $ENV{MTR_BUILD_THREAD}\n";
2229    print "Using MASTER_MYPORT         = $ENV{MASTER_MYPORT}\n";
2230    print "Using MASTER_MYPORT1        = $ENV{MASTER_MYPORT1}\n";
2231    print "Using SLAVE_MYPORT          = $ENV{SLAVE_MYPORT}\n";
2232    print "Using SLAVE_MYPORT1         = $ENV{SLAVE_MYPORT1}\n";
2233    print "Using SLAVE_MYPORT2         = $ENV{SLAVE_MYPORT2}\n";
2234    if ( ! $opt_skip_ndbcluster )
2235    {
2236      print "Using NDBCLUSTER_PORT       = $ENV{NDBCLUSTER_PORT}\n";
2237      if ( ! $opt_skip_ndbcluster_slave )
2238      {
2239	print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
2240      }
2241    }
2242    if ( ! $opt_skip_im )
2243    {
2244      print "Using IM_PORT               = $ENV{IM_PORT}\n";
2245      print "Using IM_MYSQLD1_PORT       = $ENV{IM_MYSQLD1_PORT}\n";
2246      print "Using IM_MYSQLD2_PORT       = $ENV{IM_MYSQLD2_PORT}\n";
2247    }
2248  }
2249
2250  # Create an environment variable to make it possible
2251  # to detect that valgrind is being used from test cases
2252  $ENV{'VALGRIND_TEST'}= $opt_valgrind;
2253
2254}
2255
2256
2257##############################################################################
2258#
2259#  If we get a ^C, we try to clean up before termination
2260#
2261##############################################################################
2262# FIXME check restrictions what to do in a signal handler
2263
2264sub signal_setup () {
2265  $SIG{INT}= \&handle_int_signal;
2266}
2267
2268
2269sub handle_int_signal () {
2270  $SIG{INT}= 'DEFAULT';         # If we get a ^C again, we die...
2271  mtr_warning("got INT signal, cleaning up.....");
2272  stop_all_servers();
2273  mtr_error("We die from ^C signal from user");
2274}
2275
2276
2277##############################################################################
2278#
2279#  Handle left overs from previous runs
2280#
2281##############################################################################
2282
2283sub kill_running_servers () {
2284
2285  if ( $opt_fast or $glob_use_embedded_server )
2286  {
2287    # FIXME is embedded server really using PID files?!
2288    unlink($master->[0]->{'path_pid'});
2289    unlink($master->[1]->{'path_pid'});
2290    unlink($slave->[0]->{'path_pid'});
2291    unlink($slave->[1]->{'path_pid'});
2292    unlink($slave->[2]->{'path_pid'});
2293  }
2294  else
2295  {
2296    # Ensure that no old mysqld test servers are running
2297    # This is different from terminating processes we have
2298    # started from this run of the script, this is terminating
2299    # leftovers from previous runs.
2300    mtr_kill_leftovers();
2301   }
2302}
2303
2304#
2305# Remove var and any directories in var/ created by previous
2306# tests
2307#
2308sub remove_stale_vardir () {
2309
2310  mtr_report("Removing Stale Files");
2311
2312  # Safety!
2313  mtr_error("No, don't remove the vardir when running with --extern")
2314    if $opt_extern;
2315
2316  mtr_verbose("opt_vardir: $opt_vardir");
2317  if ( $opt_vardir eq $default_vardir )
2318  {
2319    #
2320    # Running with "var" in mysql-test dir
2321    #
2322    if ( -l $opt_vardir)
2323    {
2324      # var is a symlink
2325
2326      if ( $opt_mem and readlink($opt_vardir) eq $opt_mem )
2327      {
2328	# Remove the directory which the link points at
2329	mtr_verbose("Removing " . readlink($opt_vardir));
2330	mtr_rmtree(readlink($opt_vardir));
2331
2332	# Remove the "var" symlink
2333	mtr_verbose("unlink($opt_vardir)");
2334	unlink($opt_vardir);
2335      }
2336      elsif ( $opt_mem )
2337      {
2338	# Just remove the "var" symlink
2339	mtr_report("WARNING: Removing '$opt_vardir' symlink it's wrong");
2340
2341	mtr_verbose("unlink($opt_vardir)");
2342	unlink($opt_vardir);
2343      }
2344      else
2345      {
2346	# Some users creates a soft link in mysql-test/var to another area
2347	# - allow it, but remove all files in it
2348
2349	mtr_report("WARNING: Using the 'mysql-test/var' symlink");
2350
2351	# Make sure the directory where it points exist
2352	mtr_error("The destination for symlink $opt_vardir does not exist")
2353	  if ! -d readlink($opt_vardir);
2354
2355	foreach my $bin ( glob("$opt_vardir/*") )
2356	{
2357	  mtr_verbose("Removing bin $bin");
2358	  mtr_rmtree($bin);
2359	}
2360      }
2361    }
2362    else
2363    {
2364      # Remove the entire "var" dir
2365      mtr_verbose("Removing $opt_vardir/");
2366      mtr_rmtree("$opt_vardir/");
2367    }
2368
2369    if ( $opt_mem )
2370    {
2371      # A symlink from var/ to $opt_mem will be set up
2372      # remove the $opt_mem dir to assure the symlink
2373      # won't point at an old directory
2374      mtr_verbose("Removing $opt_mem");
2375      mtr_rmtree($opt_mem);
2376    }
2377
2378  }
2379  else
2380  {
2381    #
2382    # Running with "var" in some other place
2383    #
2384
2385    # Remove the var/ dir in mysql-test dir if any
2386    # this could be an old symlink that shouldn't be there
2387    mtr_verbose("Removing $default_vardir");
2388    mtr_rmtree($default_vardir);
2389
2390    # Remove the "var" dir
2391    mtr_verbose("Removing $opt_vardir/");
2392    mtr_rmtree("$opt_vardir/");
2393  }
2394}
2395
2396#
2397# Create var and the directories needed in var
2398#
2399sub setup_vardir() {
2400  mtr_report("Creating Directories");
2401
2402  if ( $opt_vardir eq $default_vardir )
2403  {
2404    #
2405    # Running with "var" in mysql-test dir
2406    #
2407    if ( -l $opt_vardir )
2408    {
2409      #  it's a symlink
2410
2411      # Make sure the directory where it points exist
2412      mtr_error("The destination for symlink $opt_vardir does not exist")
2413	if ! -d readlink($opt_vardir);
2414    }
2415    elsif ( $opt_mem )
2416    {
2417      # Runinng with "var" as a link to some "memory" location, normally tmpfs
2418      mtr_verbose("Creating $opt_mem");
2419      mkpath($opt_mem);
2420
2421      mtr_report("Symlinking 'var' to '$opt_mem'");
2422      symlink($opt_mem, $opt_vardir);
2423    }
2424  }
2425
2426  if ( ! -d $opt_vardir )
2427  {
2428    mtr_verbose("Creating $opt_vardir");
2429    mkpath($opt_vardir);
2430  }
2431
2432  # Ensure a proper error message if vardir couldn't be created
2433  unless ( -d $opt_vardir and -w $opt_vardir )
2434  {
2435    mtr_error("Writable 'var' directory is needed, use the " .
2436	      "'--vardir=<path>' option");
2437  }
2438
2439  mkpath("$opt_vardir/log");
2440  mkpath("$opt_vardir/run");
2441  mkpath("$opt_vardir/tmp");
2442  mkpath($opt_tmpdir) if $opt_tmpdir ne "$opt_vardir/tmp";
2443
2444  # Create new data dirs
2445  foreach my $data_dir (@data_dir_lst)
2446  {
2447    mkpath("$data_dir/mysql");
2448    mkpath("$data_dir/test");
2449  }
2450
2451  # Make a link std_data_ln in var/ that points to std_data
2452  if ( ! $glob_win32 )
2453  {
2454    symlink("$glob_mysql_test_dir/std_data", "$opt_vardir/std_data_ln");
2455  }
2456  else
2457  {
2458    # on windows, copy all files from std_data into var/std_data_ln
2459    mkpath("$opt_vardir/std_data_ln");
2460    mtr_copy_dir("$glob_mysql_test_dir/std_data", "$opt_vardir/std_data_ln");
2461  }
2462
2463  # Remove old log files
2464  foreach my $name (glob("r/*.progress r/*.log r/*.warnings"))
2465  {
2466    unlink($name);
2467  }
2468}
2469
2470
2471sub  check_running_as_root () {
2472  # Check if running as root
2473  # i.e a file can be read regardless what mode we set it to
2474  my $test_file= "$opt_vardir/test_running_as_root.txt";
2475  mtr_tofile($test_file, "MySQL");
2476  chmod(oct("0000"), $test_file);
2477
2478  my $result="";
2479  if (open(FILE,"<",$test_file))
2480  {
2481    $result= join('', <FILE>);
2482    close FILE;
2483  }
2484
2485  # Some filesystems( for example CIFS) allows reading a file
2486  # although mode was set to 0000, but in that case a stat on
2487  # the file will not return 0000
2488  my $file_mode= (stat($test_file))[2] & 07777;
2489
2490  $ENV{'MYSQL_TEST_ROOT'}= "NO";
2491  mtr_verbose("result: $result, file_mode: $file_mode");
2492  if ($result eq "MySQL" && $file_mode == 0)
2493  {
2494    mtr_warning("running this script as _root_ will cause some " .
2495                "tests to be skipped");
2496    $ENV{'MYSQL_TEST_ROOT'}= "YES";
2497  }
2498
2499  chmod(oct("0755"), $test_file);
2500  unlink($test_file);
2501
2502}
2503
2504
2505sub check_ssl_support ($) {
2506  my $mysqld_variables= shift;
2507
2508  if ($opt_skip_ssl || $opt_extern)
2509  {
2510    if (!$opt_extern)
2511    {
2512      mtr_report("Skipping SSL");
2513    }
2514    $opt_ssl_supported= 0;
2515    $opt_ssl= 0;
2516    return;
2517  }
2518
2519  if ( ! $mysqld_variables->{'ssl'} )
2520  {
2521    if ( $opt_ssl)
2522    {
2523      mtr_error("Couldn't find support for SSL");
2524      return;
2525    }
2526    mtr_report("Skipping SSL, mysqld not compiled with SSL");
2527    $opt_ssl_supported= 0;
2528    $opt_ssl= 0;
2529    return;
2530  }
2531  mtr_report("Setting mysqld to support SSL connections");
2532  $opt_ssl_supported= 1;
2533}
2534
2535
2536sub check_debug_support ($) {
2537  my $mysqld_variables= shift;
2538
2539  if ( ! $mysqld_variables->{'debug'} )
2540  {
2541    #mtr_report("Binaries are not debug compiled");
2542    $debug_compiled_binaries= 0;
2543
2544    if ( $opt_debug )
2545    {
2546      mtr_error("Can't use --debug, binaries does not support it");
2547    }
2548    return;
2549  }
2550  mtr_report("Binaries are debug compiled");
2551  $debug_compiled_binaries= 1;
2552}
2553
2554##############################################################################
2555#
2556# Helper function to handle configuration-based subdirectories which Visual
2557# Studio uses for storing binaries.  If opt_vs_config is set, this returns
2558# a path based on that setting; if not, it returns paths for the default
2559# /release/ and /debug/ subdirectories.
2560#
2561# $exe can be undefined, if the directory itself will be used
2562#
2563###############################################################################
2564
2565sub vs_config_dirs ($$) {
2566  my ($path_part, $exe) = @_;
2567
2568  $exe = "" if not defined $exe;
2569
2570  if ($opt_vs_config)
2571  {
2572    return ("$glob_bindir/$path_part/$opt_vs_config/$exe");
2573  }
2574
2575  return ("$glob_bindir/$path_part/release/$exe",
2576          "$glob_bindir/$path_part/relwithdebinfo/$exe",
2577          "$glob_bindir/$path_part/debug/$exe");
2578}
2579
2580##############################################################################
2581#
2582#  Start the ndb cluster
2583#
2584##############################################################################
2585
2586sub check_ndbcluster_support ($) {
2587  my $mysqld_variables= shift;
2588
2589  if ($opt_skip_ndbcluster || $opt_extern)
2590  {
2591    if (!$opt_extern)
2592    {
2593      mtr_report("Skipping ndbcluster");
2594    }
2595    $opt_skip_ndbcluster_slave= 1;
2596    return;
2597  }
2598
2599  if ( ! $mysqld_variables->{'ndb-connectstring'} )
2600  {
2601    mtr_report("Skipping ndbcluster, mysqld not compiled with ndbcluster");
2602    $opt_skip_ndbcluster= 1;
2603    $opt_skip_ndbcluster_slave= 1;
2604    return;
2605  }
2606  $glob_ndbcluster_supported= 1;
2607  mtr_report("Using ndbcluster when necessary, mysqld supports it");
2608
2609  if ( $mysql_version_id < 50100 )
2610  {
2611    # Slave cluster is not supported until 5.1
2612    $opt_skip_ndbcluster_slave= 1;
2613
2614  }
2615
2616  return;
2617}
2618
2619
2620sub ndbcluster_start_install ($) {
2621  my $cluster= shift;
2622
2623  mtr_report("Installing $cluster->{'name'} Cluster");
2624
2625  mkdir($cluster->{'data_dir'});
2626
2627  # Create a config file from template
2628  my $ndb_no_ord=512;
2629  my $ndb_no_attr=2048;
2630  my $ndb_con_op=105000;
2631  my $ndb_dmem="80M";
2632  my $ndb_imem="24M";
2633  my $ndb_pbmem="32M";
2634  my $nodes= $cluster->{'nodes'};
2635  my $ndb_host= "localhost";
2636  my $ndb_diskless= 0;
2637
2638  if (!$opt_bench)
2639  {
2640    # Use a smaller configuration
2641    if (  $mysql_version_id < 50100 )
2642    {
2643      # 4.1 and 5.0 is using a "larger" --small configuration
2644      $ndb_no_ord=128;
2645      $ndb_con_op=10000;
2646      $ndb_dmem="40M";
2647      $ndb_imem="12M";
2648    }
2649    else
2650    {
2651      $ndb_no_ord=32;
2652      $ndb_con_op=10000;
2653      $ndb_dmem="20M";
2654      $ndb_imem="1M";
2655      $ndb_pbmem="4M";
2656    }
2657  }
2658
2659  my $config_file_template=     "lib/v1/ndb_config_${nodes}_node.ini";
2660  my $config_file= "$cluster->{'data_dir'}/config.ini";
2661
2662  open(IN, $config_file_template)
2663    or mtr_error("Can't open $config_file_template: $!");
2664  open(OUT, ">", $config_file)
2665    or mtr_error("Can't write to $config_file: $!");
2666  while (<IN>)
2667  {
2668    chomp;
2669
2670    s/CHOOSE_MaxNoOfAttributes/$ndb_no_attr/;
2671    s/CHOOSE_MaxNoOfOrderedIndexes/$ndb_no_ord/;
2672    s/CHOOSE_MaxNoOfConcurrentOperations/$ndb_con_op/;
2673    s/CHOOSE_DataMemory/$ndb_dmem/;
2674    s/CHOOSE_IndexMemory/$ndb_imem/;
2675    s/CHOOSE_Diskless/$ndb_diskless/;
2676    s/CHOOSE_HOSTNAME_.*/$ndb_host/;
2677    s/CHOOSE_FILESYSTEM/$cluster->{'data_dir'}/;
2678    s/CHOOSE_PORT_MGM/$cluster->{'port'}/;
2679    if ( $mysql_version_id < 50000 )
2680    {
2681      my $base_port= $cluster->{'port'} + 1;
2682      s/CHOOSE_PORT_TRANSPORTER/$base_port/;
2683    }
2684    s/CHOOSE_DiskPageBufferMemory/$ndb_pbmem/;
2685
2686    print OUT "$_ \n";
2687  }
2688  close OUT;
2689  close IN;
2690
2691
2692  # Start cluster with "--initial"
2693
2694  ndbcluster_start($cluster, "--initial");
2695
2696  return 0;
2697}
2698
2699
2700sub ndbcluster_wait_started($$){
2701  my $cluster= shift;
2702  my $ndb_waiter_extra_opt= shift;
2703  my $path_waiter_log= "$cluster->{'data_dir'}/ndb_waiter.log";
2704  my $args;
2705
2706  mtr_init_args(\$args);
2707
2708  mtr_add_arg($args, "--no-defaults");
2709  mtr_add_arg($args, "--core");
2710  mtr_add_arg($args, "--ndb-connectstring=%s", $cluster->{'connect_string'});
2711  mtr_add_arg($args, "--timeout=60");
2712
2713  if ($ndb_waiter_extra_opt)
2714  {
2715    mtr_add_arg($args, "$ndb_waiter_extra_opt");
2716  }
2717
2718  # Start the ndb_waiter which will connect to the ndb_mgmd
2719  # and poll it for state of the ndbd's, will return when
2720  # all nodes in the cluster is started
2721  my $res= mtr_run($exe_ndb_waiter, $args,
2722		   "", $path_waiter_log, $path_waiter_log, "");
2723  mtr_verbose("ndbcluster_wait_started, returns: $res") if $res;
2724  return $res;
2725}
2726
2727
2728
2729sub mysqld_wait_started($){
2730  my $mysqld= shift;
2731
2732  if (sleep_until_file_created($mysqld->{'path_pid'},
2733			       $mysqld->{'start_timeout'},
2734			       $mysqld->{'pid'}) == 0)
2735  {
2736    # Failed to wait for pid file
2737    return 1;
2738  }
2739
2740  # Get the "real pid" of the process, it will be used for killing
2741  # the process in ActiveState's perl on windows
2742  $mysqld->{'real_pid'}= mtr_get_pid_from_file($mysqld->{'path_pid'});
2743
2744  return 0;
2745}
2746
2747
2748sub ndb_mgmd_wait_started($) {
2749  my ($cluster)= @_;
2750
2751  my $retries= 100;
2752  while (ndbcluster_wait_started($cluster, "--no-contact") and
2753	 $retries)
2754  {
2755    # Millisceond sleep emulated with select
2756    select(undef, undef, undef, (0.1));
2757
2758    $retries--;
2759  }
2760
2761  return $retries == 0;
2762
2763}
2764
2765sub ndb_mgmd_start ($) {
2766  my $cluster= shift;
2767
2768  my $args;                             # Arg vector
2769  my $pid= -1;
2770
2771  mtr_init_args(\$args);
2772  mtr_add_arg($args, "--no-defaults");
2773  mtr_add_arg($args, "--core");
2774  mtr_add_arg($args, "--nodaemon");
2775  mtr_add_arg($args, "--config-file=%s", "$cluster->{'data_dir'}/config.ini");
2776
2777
2778  my $path_ndb_mgmd_log= "$cluster->{'data_dir'}/\l$cluster->{'name'}_ndb_mgmd.log";
2779  $pid= mtr_spawn($exe_ndb_mgmd, $args, "",
2780		  $path_ndb_mgmd_log,
2781		  $path_ndb_mgmd_log,
2782		  "",
2783		  { append_log_file => 1 });
2784
2785  # FIXME Should not be needed
2786  # Unfortunately the cluster nodes will fail to start
2787  # if ndb_mgmd has not started properly
2788  if (ndb_mgmd_wait_started($cluster))
2789  {
2790    mtr_error("Failed to wait for start of ndb_mgmd");
2791  }
2792
2793  # Remember pid of ndb_mgmd
2794  $cluster->{'pid'}= $pid;
2795
2796  mtr_verbose("ndb_mgmd_start, pid: $pid");
2797
2798  return $pid;
2799}
2800
2801
2802sub ndbd_start ($$$) {
2803  my $cluster= shift;
2804  my $idx= shift;
2805  my $extra_args= shift;
2806
2807  my $args;                             # Arg vector
2808  my $pid= -1;
2809
2810  mtr_init_args(\$args);
2811  mtr_add_arg($args, "--no-defaults");
2812  mtr_add_arg($args, "--core");
2813  mtr_add_arg($args, "--ndb-connectstring=%s", "$cluster->{'connect_string'}");
2814  if ( $mysql_version_id >= 50000)
2815  {
2816    mtr_add_arg($args, "--character-sets-dir=%s", "$path_charsetsdir");
2817  }
2818  mtr_add_arg($args, "--nodaemon");
2819  mtr_add_arg($args, "$extra_args");
2820
2821  my $nodeid= $cluster->{'ndbds'}->[$idx]->{'nodeid'};
2822  my $path_ndbd_log= "$cluster->{'data_dir'}/ndb_${nodeid}.log";
2823  $pid= mtr_spawn($exe_ndbd, $args, "",
2824		  $path_ndbd_log,
2825		  $path_ndbd_log,
2826		  "",
2827		  { append_log_file => 1 });
2828
2829  # Add pid to list of pids for this cluster
2830  $cluster->{'ndbds'}->[$idx]->{'pid'}= $pid;
2831
2832  # Rememeber options used when starting
2833  $cluster->{'ndbds'}->[$idx]->{'start_extra_args'}= $extra_args;
2834  $cluster->{'ndbds'}->[$idx]->{'idx'}= $idx;
2835
2836  mtr_verbose("ndbd_start, pid: $pid");
2837
2838  return $pid;
2839}
2840
2841
2842sub ndbcluster_start ($$) {
2843  my $cluster= shift;
2844  my $extra_args= shift;
2845
2846  mtr_verbose("ndbcluster_start '$cluster->{'name'}'");
2847
2848  if ( $cluster->{'use_running'} )
2849  {
2850    return 0;
2851  }
2852
2853  if ( $cluster->{'pid'} )
2854  {
2855    mtr_error("Cluster '$cluster->{'name'}' already started");
2856  }
2857
2858  ndb_mgmd_start($cluster);
2859
2860  for ( my $idx= 0; $idx < $cluster->{'nodes'}; $idx++ )
2861  {
2862    ndbd_start($cluster, $idx, $extra_args);
2863  }
2864
2865  return 0;
2866}
2867
2868
2869sub rm_ndbcluster_tables ($) {
2870  my $dir=       shift;
2871  foreach my $bin ( glob("$dir/mysql/ndb_apply_status*"),
2872                    glob("$dir/mysql/ndb_schema*"))
2873  {
2874    unlink($bin);
2875  }
2876}
2877
2878
2879##############################################################################
2880#
2881#  Run the benchmark suite
2882#
2883##############################################################################
2884
2885sub run_benchmarks ($) {
2886  my $benchmark=  shift;
2887
2888  my $args;
2889
2890  if ( ! $glob_use_embedded_server )
2891  {
2892    mysqld_start($master->[0],[],[]);
2893    if ( ! $master->[0]->{'pid'} )
2894    {
2895      mtr_error("Can't start the mysqld server");
2896    }
2897  }
2898
2899  mtr_init_args(\$args);
2900
2901  mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'});
2902  mtr_add_arg($args, "--user=%s", $opt_user);
2903
2904  if ( $opt_small_bench )
2905  {
2906    mtr_add_arg($args, "--small-test");
2907    mtr_add_arg($args, "--small-tables");
2908  }
2909
2910  if ( $opt_with_ndbcluster )
2911  {
2912    mtr_add_arg($args, "--create-options=TYPE=ndb");
2913  }
2914
2915  chdir($glob_mysql_bench_dir)
2916    or mtr_error("Couldn't chdir to '$glob_mysql_bench_dir': $!");
2917
2918  if ( ! $benchmark )
2919  {
2920    mtr_add_arg($args, "--general-log");
2921    mtr_run("$glob_mysql_bench_dir/run-all-tests", $args, "", "", "", "");
2922    # FIXME check result code?!
2923  }
2924  elsif ( -x $benchmark )
2925  {
2926    mtr_run("$glob_mysql_bench_dir/$benchmark", $args, "", "", "", "");
2927    # FIXME check result code?!
2928  }
2929  else
2930  {
2931    mtr_error("Benchmark $benchmark not found");
2932  }
2933
2934  chdir($glob_mysql_test_dir);          # Go back
2935
2936  if ( ! $glob_use_embedded_server )
2937  {
2938    stop_masters();
2939  }
2940}
2941
2942
2943##############################################################################
2944#
2945#  Run the tests
2946#
2947##############################################################################
2948
2949sub run_tests () {
2950  my ($tests)= @_;
2951
2952  mtr_print_thick_line();
2953
2954  mtr_timer_start($glob_timers,"suite", 60 * $opt_suite_timeout);
2955
2956  mtr_report_tests_not_skipped_though_disabled($tests);
2957
2958  mtr_print_header();
2959
2960  foreach my $tinfo ( @$tests )
2961  {
2962    if (run_testcase_check_skip_test($tinfo))
2963    {
2964      next;
2965    }
2966
2967    mtr_timer_start($glob_timers,"testcase", 60 * $opt_testcase_timeout);
2968    run_testcase($tinfo);
2969    mtr_timer_stop($glob_timers,"testcase");
2970  }
2971
2972  mtr_print_line();
2973
2974  if ( ! $glob_debugger and
2975       ! $opt_extern and
2976       ! $glob_use_embedded_server )
2977  {
2978    stop_all_servers();
2979  }
2980
2981  if ( $opt_gcov )
2982  {
2983    gcov_collect(); # collect coverage information
2984  }
2985  if ( $opt_gprof )
2986  {
2987    gprof_collect(); # collect coverage information
2988  }
2989
2990  mtr_report_stats($tests);
2991
2992  mtr_timer_stop($glob_timers,"suite");
2993}
2994
2995
2996##############################################################################
2997#
2998#  Initiate the test databases
2999#
3000##############################################################################
3001
3002sub initialize_servers () {
3003
3004  datadir_list_setup();
3005
3006  if ( $opt_extern )
3007  {
3008    # Running against an already started server, if the specified
3009    # vardir does not already exist it should be created
3010    if ( ! -d $opt_vardir )
3011    {
3012      mtr_report("Creating '$opt_vardir'");
3013      setup_vardir();
3014    }
3015    else
3016    {
3017      mtr_verbose("No need to create '$opt_vardir' it already exists");
3018    }
3019  }
3020  else
3021  {
3022    kill_running_servers();
3023
3024    if ( ! $opt_start_dirty )
3025    {
3026      remove_stale_vardir();
3027      setup_vardir();
3028
3029      mysql_install_db();
3030      if ( $opt_force )
3031      {
3032	# Save a snapshot of the freshly installed db
3033	# to make it possible to restore to a known point in time
3034	save_installed_db();
3035      }
3036    }
3037  }
3038  check_running_as_root();
3039
3040  mtr_log_init("$opt_vardir/log/mysql-test-run.log");
3041
3042}
3043
3044sub mysql_install_db () {
3045
3046  install_db('master', $master->[0]->{'path_myddir'});
3047
3048  if ($max_master_num > 1)
3049  {
3050    copy_install_db('master', $master->[1]->{'path_myddir'});
3051  }
3052
3053  # Install the number of slave databses needed
3054  for (my $idx= 0; $idx < $max_slave_num; $idx++)
3055  {
3056    copy_install_db("slave".($idx+1), $slave->[$idx]->{'path_myddir'});
3057  }
3058
3059  if ( ! $opt_skip_im )
3060  {
3061    im_prepare_env($instance_manager);
3062  }
3063
3064  my $cluster_started_ok= 1; # Assume it can be started
3065
3066  my $cluster= $clusters->[0]; # Master cluster
3067  if ($opt_skip_ndbcluster ||
3068      $cluster->{'use_running'} ||
3069      $cluster->{executable_setup_failed})
3070  {
3071    # Don't install master cluster
3072  }
3073  elsif (ndbcluster_start_install($cluster))
3074  {
3075    mtr_warning("Failed to start install of $cluster->{name}");
3076    $cluster_started_ok= 0;
3077  }
3078
3079  $cluster= $clusters->[1]; # Slave cluster
3080  if ($max_slave_num == 0 ||
3081      $opt_skip_ndbcluster_slave ||
3082      $cluster->{'use_running'} ||
3083      $cluster->{executable_setup_failed})
3084  {
3085    # Don't install slave cluster
3086  }
3087  elsif (ndbcluster_start_install($cluster))
3088  {
3089    mtr_warning("Failed to start install of $cluster->{name}");
3090    $cluster_started_ok= 0;
3091  }
3092
3093  foreach $cluster (@{$clusters})
3094  {
3095
3096    next if !$cluster->{'pid'};
3097
3098    $cluster->{'installed_ok'}= 1; # Assume install suceeds
3099
3100    if (ndbcluster_wait_started($cluster, ""))
3101    {
3102      # failed to install, disable usage and flag that its no ok
3103      mtr_report("ndbcluster_install of $cluster->{'name'} failed");
3104      $cluster->{"installed_ok"}= 0;
3105
3106      $cluster_started_ok= 0;
3107    }
3108  }
3109
3110  if ( ! $cluster_started_ok )
3111  {
3112    if ( $opt_force)
3113    {
3114      # Continue without cluster
3115    }
3116    else
3117    {
3118      mtr_error("To continue, re-run with '--force'.");
3119    }
3120  }
3121
3122  return 0;
3123}
3124
3125
3126sub copy_install_db ($$) {
3127  my $type=      shift;
3128  my $data_dir=  shift;
3129
3130  mtr_report("Installing \u$type Database");
3131
3132  # Just copy the installed db from first master
3133  mtr_copy_dir($master->[0]->{'path_myddir'}, $data_dir);
3134
3135}
3136
3137
3138sub install_db ($$) {
3139  my $type=      shift;
3140  my $data_dir=  shift;
3141
3142  mtr_report("Installing \u$type Database");
3143
3144
3145  my $args;
3146  mtr_init_args(\$args);
3147  mtr_add_arg($args, "--no-defaults");
3148  mtr_add_arg($args, "--bootstrap");
3149  mtr_add_arg($args, "--basedir=%s", $glob_basedir);
3150  mtr_add_arg($args, "--datadir=%s", $data_dir);
3151  mtr_add_arg($args, "--loose-skip-ndbcluster");
3152  mtr_add_arg($args, "--tmpdir=.");
3153  mtr_add_arg($args, "--core-file");
3154
3155  if ( $opt_debug )
3156  {
3157    mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap_%s.trace",
3158		$path_vardir_trace, $type);
3159  }
3160
3161  mtr_add_arg($args, "--lc-messages-dir=%s", $path_language);
3162  mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
3163
3164  # InnoDB arguments that affect file location and sizes may
3165  # need to be given to the bootstrap process as well as the
3166  # server process.
3167  foreach my $extra_opt ( @opt_extra_mysqld_opt ) {
3168    if ($extra_opt =~ /--innodb/) {
3169      mtr_add_arg($args, $extra_opt);
3170    }
3171  }
3172
3173  # If DISABLE_GRANT_OPTIONS is defined when the server is compiled (e.g.,
3174  # configure --disable-grant-options), mysqld will not recognize the
3175  # --bootstrap or --skip-grant-tables options.  The user can set
3176  # MYSQLD_BOOTSTRAP to the full path to a mysqld which does accept
3177  # --bootstrap, to accommodate this.
3178  my $exe_mysqld_bootstrap = $ENV{'MYSQLD_BOOTSTRAP'} || $exe_mysqld;
3179
3180  # ----------------------------------------------------------------------
3181  # export MYSQLD_BOOTSTRAP_CMD variable containing <path>/mysqld <args>
3182  # ----------------------------------------------------------------------
3183  $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args);
3184
3185  # ----------------------------------------------------------------------
3186  # Create the bootstrap.sql file
3187  # ----------------------------------------------------------------------
3188  my $bootstrap_sql_file= "$opt_vardir/tmp/bootstrap.sql";
3189
3190  # Use the mysql database for system tables
3191  mtr_tofile($bootstrap_sql_file, "use mysql;\n");
3192
3193  # Add the offical mysql system tables
3194  # for a production system
3195  mtr_appendfile_to_file("$path_sql_dir/mysql_system_tables.sql",
3196			 $bootstrap_sql_file);
3197
3198  # Add the mysql system tables initial data
3199  # for a production system
3200  mtr_appendfile_to_file("$path_sql_dir/mysql_system_tables_data.sql",
3201			 $bootstrap_sql_file);
3202
3203  # Add test data for timezone - this is just a subset, on a real
3204  # system these tables will be populated either by mysql_tzinfo_to_sql
3205  # or by downloading the timezone table package from our website
3206  mtr_appendfile_to_file("$path_sql_dir/mysql_test_data_timezone.sql",
3207			 $bootstrap_sql_file);
3208
3209  # Fill help tables, just an empty file when running from bk repo
3210  # but will be replaced by a real fill_help_tables.sql when
3211  # building the source dist
3212  mtr_appendfile_to_file("$path_sql_dir/fill_help_tables.sql",
3213			 $bootstrap_sql_file);
3214
3215  # Remove anonymous users
3216  mtr_tofile($bootstrap_sql_file,
3217	     "DELETE FROM mysql.user where user= '';");
3218
3219  # Log bootstrap command
3220  my $path_bootstrap_log= "$opt_vardir/log/bootstrap.log";
3221  mtr_tofile($path_bootstrap_log,
3222	     "$exe_mysqld_bootstrap " . join(" ", @$args) . "\n");
3223
3224
3225  if ( mtr_run($exe_mysqld_bootstrap, $args, $bootstrap_sql_file,
3226               $path_bootstrap_log, $path_bootstrap_log,
3227	       "", { append_log_file => 1 }) != 0 )
3228
3229  {
3230    mtr_error("Error executing mysqld --bootstrap\n" .
3231              "Could not install system database from $bootstrap_sql_file\n" .
3232	      "see $path_bootstrap_log for errors");
3233  }
3234}
3235
3236
3237sub im_prepare_env($) {
3238  my $instance_manager = shift;
3239
3240  im_create_passwd_file($instance_manager);
3241  im_prepare_data_dir($instance_manager);
3242}
3243
3244
3245sub im_create_passwd_file($) {
3246  my $instance_manager = shift;
3247
3248  my $pwd_file_path = $instance_manager->{'password_file'};
3249
3250  mtr_report("Creating IM password file ($pwd_file_path)");
3251
3252  open(OUT, ">", $pwd_file_path)
3253    or mtr_error("Can't write to $pwd_file_path: $!");
3254
3255  print OUT $instance_manager->{'admin_login'}, ":",
3256        $instance_manager->{'admin_sha1'}, "\n";
3257
3258  close(OUT);
3259}
3260
3261
3262sub im_create_defaults_file($) {
3263  my $instance_manager = shift;
3264
3265  my $defaults_file = $instance_manager->{'defaults_file'};
3266
3267  open(OUT, ">", $defaults_file)
3268    or mtr_error("Can't write to $defaults_file: $!");
3269
3270  print OUT <<EOF
3271[mysql]
3272
3273[manager]
3274pid-file            = $instance_manager->{path_pid}
3275angel-pid-file      = $instance_manager->{path_angel_pid}
3276socket              = $instance_manager->{path_sock}
3277port                = $instance_manager->{port}
3278password-file       = $instance_manager->{password_file}
3279default-mysqld-path = $exe_mysqld
3280
3281EOF
3282;
3283
3284  foreach my $instance (@{$instance_manager->{'instances'}})
3285  {
3286    my $server_id = $instance->{'server_id'};
3287
3288    print OUT <<EOF
3289[mysqld$server_id]
3290socket              = $instance->{path_sock}
3291pid-file            = $instance->{path_pid}
3292port                = $instance->{port}
3293datadir             = $instance->{path_datadir}
3294lc-messages-dir     = $path_language
3295log                 = $instance->{path_datadir}/mysqld$server_id.log
3296log-error           = $instance->{path_datadir}/mysqld$server_id.err.log
3297log-slow-queries    = $instance->{path_datadir}/mysqld$server_id.slow.log
3298character-sets-dir  = $path_charsetsdir
3299basedir             = $glob_basedir
3300server_id           = $server_id
3301shutdown-delay      = 10
3302skip-stack-trace
3303loose-skip-innodb
3304loose-skip-ndbcluster
3305EOF
3306;
3307    if ( $mysql_version_id < 50100 )
3308    {
3309      print OUT "skip-bdb\n";
3310    }
3311    print OUT "nonguarded\n" if $instance->{'nonguarded'};
3312    if ( $mysql_version_id >= 50100 )
3313    {
3314      print OUT "log-output=FILE\n" if $instance->{'old_log_format'};
3315    }
3316    print OUT "\n";
3317  }
3318
3319  close(OUT);
3320}
3321
3322
3323sub im_prepare_data_dir($) {
3324  my $instance_manager = shift;
3325
3326  foreach my $instance (@{$instance_manager->{'instances'}})
3327  {
3328    copy_install_db(
3329      'im_mysqld_' . $instance->{'server_id'},
3330      $instance->{'path_datadir'});
3331  }
3332}
3333
3334
3335
3336#
3337# Restore snapshot of the installed slave databases
3338# if the snapshot exists
3339#
3340sub restore_slave_databases ($) {
3341  my ($num_slaves)= @_;
3342
3343  if ( -d $path_snapshot)
3344  {
3345    for (my $idx= 0; $idx < $num_slaves; $idx++)
3346    {
3347      my $data_dir= $slave->[$idx]->{'path_myddir'};
3348      my $name= basename($data_dir);
3349      mtr_rmtree($data_dir);
3350      mtr_copy_dir("$path_snapshot/$name", $data_dir);
3351    }
3352  }
3353}
3354
3355
3356sub run_testcase_check_skip_test($)
3357{
3358  my ($tinfo)= @_;
3359
3360  # ----------------------------------------------------------------------
3361  # If marked to skip, just print out and return.
3362  # Note that a test case not marked as 'skip' can still be
3363  # skipped later, because of the test case itself in cooperation
3364  # with the mysqltest program tells us so.
3365  # ----------------------------------------------------------------------
3366
3367  if ( $tinfo->{'skip'} )
3368  {
3369    mtr_report_test_name($tinfo);
3370    mtr_report_test_skipped($tinfo);
3371    return 1;
3372  }
3373
3374  if ($tinfo->{'ndb_test'})
3375  {
3376    foreach my $cluster (@{$clusters})
3377    {
3378      # Slave cluster is skipped and thus not
3379      # installed, no need to perform checks
3380      last if ($opt_skip_ndbcluster_slave and
3381	       $cluster->{'name'} eq 'Slave');
3382
3383      # Using running cluster - no need
3384      # to check if test should be skipped
3385      # will be done by test itself
3386      last if ($cluster->{'use_running'});
3387
3388      # If test needs this cluster, check binaries was found ok
3389      if ( $cluster->{'executable_setup_failed'} )
3390      {
3391	mtr_report_test_name($tinfo);
3392	$tinfo->{comment}=
3393	  "Failed to find cluster binaries";
3394	mtr_report_test_failed($tinfo);
3395	return 1;
3396      }
3397
3398      # If test needs this cluster, check it was installed ok
3399      if ( !$cluster->{'installed_ok'} )
3400      {
3401	mtr_report_test_name($tinfo);
3402	$tinfo->{comment}=
3403	  "Cluster $cluster->{'name'} was not installed ok";
3404	mtr_report_test_failed($tinfo);
3405	return 1;
3406      }
3407
3408    }
3409  }
3410
3411  if ( $tinfo->{'component_id'} eq 'im' )
3412  {
3413      # If test needs im, check binaries was found ok
3414    if ( $instance_manager->{'executable_setup_failed'} )
3415    {
3416      mtr_report_test_name($tinfo);
3417      $tinfo->{comment}=
3418	"Failed to find MySQL manager binaries";
3419      mtr_report_test_failed($tinfo);
3420      return 1;
3421    }
3422  }
3423
3424  return 0;
3425}
3426
3427
3428sub do_before_run_mysqltest($)
3429{
3430  my $tinfo= shift;
3431  my $args;
3432
3433  # Remove old files produced by mysqltest
3434  my $base_file= mtr_match_extension($tinfo->{'result_file'},
3435				    "result"); # Trim extension
3436  unlink("$base_file.reject");
3437  unlink("$base_file.progress");
3438  unlink("$base_file.log");
3439  unlink("$base_file.warnings");
3440
3441  if (!$opt_extern)
3442  {
3443    if ( $mysql_version_id < 50000 ) {
3444      # Set environment variable NDB_STATUS_OK to 1
3445      # if script decided to run mysqltest cluster _is_ installed ok
3446      $ENV{'NDB_STATUS_OK'} = "1";
3447    } elsif ( $mysql_version_id < 50100 ) {
3448      # Set environment variable NDB_STATUS_OK to YES
3449      # if script decided to run mysqltest cluster _is_ installed ok
3450      $ENV{'NDB_STATUS_OK'} = "YES";
3451    }
3452    if (defined $tinfo->{binlog_format} and  $mysql_version_id > 50100 )
3453    {
3454      # Dynamically switch binlog format of
3455      # master, slave is always restarted
3456      foreach my $server ( @$master )
3457      {
3458        next unless ($server->{'pid'});
3459
3460	mtr_init_args(\$args);
3461	mtr_add_arg($args, "--no-defaults");
3462	mtr_add_arg($args, "--user=root");
3463	mtr_add_arg($args, "--port=$server->{'port'}");
3464	mtr_add_arg($args, "--socket=$server->{'path_sock'}");
3465
3466	my $sql= "include/set_binlog_format_".$tinfo->{binlog_format}.".sql";
3467	mtr_verbose("Setting binlog format:", $tinfo->{binlog_format});
3468	if (mtr_run($exe_mysql, $args, $sql, "", "", "") != 0)
3469	{
3470	  mtr_error("Failed to switch binlog format");
3471	}
3472      }
3473    }
3474  }
3475}
3476
3477sub do_after_run_mysqltest($)
3478{
3479  my $tinfo= shift;
3480
3481  # Save info from this testcase run to mysqltest.log
3482  mtr_appendfile_to_file($path_current_test_log, $path_mysqltest_log)
3483    if -f $path_current_test_log;
3484  mtr_appendfile_to_file($path_timefile, $path_mysqltest_log)
3485    if -f $path_timefile;
3486}
3487
3488
3489sub run_testcase_mark_logs($$)
3490{
3491  my ($tinfo, $log_msg)= @_;
3492
3493  # Write a marker to all log files
3494
3495  # The file indicating current test name
3496  mtr_tonewfile($path_current_test_log, $log_msg);
3497
3498  # each mysqld's .err file
3499  foreach my $mysqld (@{$master}, @{$slave})
3500  {
3501    mtr_tofile($mysqld->{path_myerr}, $log_msg);
3502  }
3503
3504  if ( $tinfo->{'component_id'} eq 'im')
3505  {
3506    mtr_tofile($instance_manager->{path_err}, $log_msg);
3507    mtr_tofile($instance_manager->{path_log}, $log_msg);
3508  }
3509
3510  # ndbcluster log file
3511  mtr_tofile($path_ndb_testrun_log, $log_msg);
3512
3513}
3514
3515sub find_testcase_skipped_reason($)
3516{
3517  my ($tinfo)= @_;
3518
3519  # Set default message
3520  $tinfo->{'comment'}= "Detected by testcase(no log file)";
3521
3522  # Open mysqltest-time(the mysqltest log file)
3523  my $F= IO::File->new($path_timefile)
3524    or return;
3525  my $reason;
3526
3527  while ( my $line= <$F> )
3528  {
3529    # Look for "reason: <reason for skipping test>"
3530    if ( $line =~ /reason: (.*)/ )
3531    {
3532      $reason= $1;
3533    }
3534  }
3535
3536  if ( ! $reason )
3537  {
3538    mtr_warning("Could not find reason for skipping test in $path_timefile");
3539    $reason= "Detected by testcase(reason unknown) ";
3540  }
3541  $tinfo->{'comment'}= $reason;
3542}
3543
3544
3545##############################################################################
3546#
3547#  Run a single test case
3548#
3549##############################################################################
3550
3551# When we get here, we have already filtered out test cases that doesn't
3552# apply to the current setup, for example if we use a running server, test
3553# cases that restart the server are dropped. So this function should mostly
3554# be about doing things, not a lot of logic.
3555
3556# We don't start and kill the servers for each testcase. But some
3557# testcases needs a restart, because they specify options to start
3558# mysqld with. After that testcase, we need to restart again, to set
3559# back the normal options.
3560
3561sub run_testcase ($) {
3562  my $tinfo=  shift;
3563
3564  # -------------------------------------------------------
3565  # Init variables that can change between each test case
3566  # -------------------------------------------------------
3567
3568  $ENV{'TZ'}= $tinfo->{'timezone'};
3569  mtr_verbose("Setting timezone: $tinfo->{'timezone'}");
3570
3571  my $master_restart= run_testcase_need_master_restart($tinfo);
3572  my $slave_restart= run_testcase_need_slave_restart($tinfo);
3573
3574  if ($master_restart or $slave_restart)
3575  {
3576    # Can't restart a running server that may be in use
3577    if ( $opt_extern )
3578    {
3579      mtr_report_test_name($tinfo);
3580      $tinfo->{comment}= "Can't restart a running server";
3581      mtr_report_test_skipped($tinfo);
3582      return;
3583    }
3584
3585    run_testcase_stop_servers($tinfo, $master_restart, $slave_restart);
3586  }
3587
3588  # Write to all log files to indicate start of testcase
3589  run_testcase_mark_logs($tinfo, "CURRENT_TEST: $tinfo->{name}\n");
3590
3591  my $died= mtr_record_dead_children();
3592  if ($died or $master_restart or $slave_restart)
3593  {
3594    if (run_testcase_start_servers($tinfo))
3595    {
3596      mtr_report_test_name($tinfo);
3597      report_failure_and_restart($tinfo);
3598      return 1;
3599    }
3600  }
3601  elsif ($glob_use_embedded_server)
3602  {
3603    run_master_init_script($tinfo);
3604  }
3605
3606  # ----------------------------------------------------------------------
3607  # If --start-and-exit or --start-dirty given, stop here to let user manually
3608  # run tests
3609  # ----------------------------------------------------------------------
3610  if ( $opt_start_and_exit or $opt_start_dirty )
3611  {
3612    mtr_timer_stop_all($glob_timers);
3613    mtr_report("\nServers started, exiting");
3614    if ($glob_win32_perl)
3615    {
3616      #ActiveState perl hangs  when using normal exit, use  POSIX::_exit instead
3617      use POSIX qw[ _exit ];
3618      POSIX::_exit(0);
3619    }
3620    else
3621    {
3622      exit(0);
3623    }
3624  }
3625
3626  {
3627    do_before_run_mysqltest($tinfo);
3628
3629    my $res= run_mysqltest($tinfo);
3630    mtr_report_test_name($tinfo);
3631
3632    do_after_run_mysqltest($tinfo);
3633
3634    if ( $res == 0 )
3635    {
3636      mtr_report_test_passed($tinfo);
3637    }
3638    elsif ( $res == 62 )
3639    {
3640      # Testcase itself tell us to skip this one
3641
3642      # Try to get reason from mysqltest.log
3643      find_testcase_skipped_reason($tinfo);
3644      mtr_report_test_skipped($tinfo);
3645    }
3646    elsif ( $res == 63 )
3647    {
3648      $tinfo->{'timeout'}= 1;           # Mark as timeout
3649      report_failure_and_restart($tinfo);
3650    }
3651    elsif ( $res == 1 )
3652    {
3653      # Test case failure reported by mysqltest
3654      report_failure_and_restart($tinfo);
3655    }
3656    else
3657    {
3658      # mysqltest failed, probably crashed
3659      $tinfo->{comment}=
3660	"mysqltest returned unexpected code $res, it has probably crashed";
3661      report_failure_and_restart($tinfo);
3662    }
3663  }
3664
3665  # Remove the file that mysqltest writes info to
3666  unlink($path_timefile);
3667
3668  # ----------------------------------------------------------------------
3669  # Stop Instance Manager if we are processing an IM-test case.
3670  # ----------------------------------------------------------------------
3671  if ( $tinfo->{'component_id'} eq 'im' and
3672       !mtr_im_stop($instance_manager, $tinfo->{'name'}))
3673  {
3674    mtr_error("Failed to stop Instance Manager.")
3675  }
3676}
3677
3678
3679#
3680# Save a snapshot of the installed test db(s)
3681# I.e take a snapshot of the var/ dir
3682#
3683sub save_installed_db () {
3684
3685  mtr_report("Saving snapshot of installed databases");
3686  mtr_rmtree($path_snapshot);
3687
3688  foreach my $data_dir (@data_dir_lst)
3689  {
3690    my $name= basename($data_dir);
3691    mtr_copy_dir("$data_dir", "$path_snapshot/$name");
3692  }
3693}
3694
3695
3696#
3697# Save any interesting files in the data_dir
3698# before the data dir is removed.
3699#
3700sub save_files_before_restore($$) {
3701  my $test_name= shift;
3702  my $data_dir= shift;
3703  my $save_name= "$opt_vardir/log/$test_name";
3704
3705  # Look for core files
3706  foreach my $core_file ( glob("$data_dir/core*") )
3707  {
3708    last if $opt_max_save_core > 0 && $num_saved_cores >= $opt_max_save_core;
3709    my $core_name= basename($core_file);
3710    mtr_report("Saving $core_name");
3711    mkdir($save_name) if ! -d $save_name;
3712    rename("$core_file", "$save_name/$core_name");
3713    ++$num_saved_cores;
3714  }
3715}
3716
3717
3718#
3719# Restore snapshot of the installed test db(s)
3720# if the snapshot exists
3721#
3722sub restore_installed_db ($) {
3723  my $test_name= shift;
3724
3725  if ( -d $path_snapshot)
3726  {
3727    mtr_report("Restoring snapshot of databases");
3728
3729    foreach my $data_dir (@data_dir_lst)
3730    {
3731      my $name= basename($data_dir);
3732      save_files_before_restore($test_name, $data_dir);
3733      mtr_rmtree("$data_dir");
3734      mtr_copy_dir("$path_snapshot/$name", "$data_dir");
3735    }
3736
3737    # Remove the ndb_*_fs dirs for all ndbd nodes
3738    # forcing a clean start of ndb
3739    foreach my $cluster (@{$clusters})
3740    {
3741      foreach my $ndbd (@{$cluster->{'ndbds'}})
3742      {
3743	mtr_rmtree("$ndbd->{'path_fs'}" );
3744      }
3745    }
3746  }
3747  else
3748  {
3749    # No snapshot existed
3750    mtr_error("No snapshot existed");
3751  }
3752}
3753
3754sub report_failure_and_restart ($) {
3755  my $tinfo= shift;
3756
3757  mtr_report_test_failed($tinfo);
3758  print "\n";
3759  if ( $opt_force )
3760  {
3761    # Stop all servers that are known to be running
3762    stop_all_servers();
3763
3764    # Restore the snapshot of the installed test db
3765    restore_installed_db($tinfo->{'name'});
3766    mtr_report("Resuming Tests\n");
3767    return;
3768  }
3769
3770  my $test_mode= join(" ", @::glob_test_mode) || "default";
3771  mtr_report("Aborting: $tinfo->{'name'} failed in $test_mode mode. ");
3772  mtr_report("To continue, re-run with '--force'.");
3773  if ( ! $glob_debugger and
3774       ! $opt_extern and
3775       ! $glob_use_embedded_server )
3776  {
3777    stop_all_servers();
3778  }
3779  mtr_exit(1);
3780
3781}
3782
3783
3784sub run_master_init_script ($) {
3785  my ($tinfo)= @_;
3786  my $init_script= $tinfo->{'master_sh'};
3787
3788  # Run master initialization shell script if one exists
3789  if ( $init_script )
3790  {
3791    my $ret= mtr_run("/bin/sh", [$init_script], "", "", "", "");
3792    if ( $ret != 0 )
3793    {
3794      # FIXME rewrite those scripts to return 0 if successful
3795      # mtr_warning("$init_script exited with code $ret");
3796    }
3797  }
3798}
3799
3800
3801##############################################################################
3802#
3803#  Start and stop servers
3804#
3805##############################################################################
3806
3807
3808sub do_before_start_master ($) {
3809  my ($tinfo)= @_;
3810
3811  my $tname= $tinfo->{'name'};
3812
3813  # FIXME what about second master.....
3814
3815  # Don't delete anything if starting dirty
3816  return if ($opt_start_dirty);
3817
3818  foreach my $bin ( glob("$opt_vardir/log/master*-bin*") )
3819  {
3820    unlink($bin);
3821  }
3822
3823  # FIXME only remove the ones that are tied to this master
3824  # Remove old master.info and relay-log.info files
3825  unlink("$master->[0]->{'path_myddir'}/master.info");
3826  unlink("$master->[0]->{'path_myddir'}/relay-log.info");
3827  unlink("$master->[1]->{'path_myddir'}/master.info");
3828  unlink("$master->[1]->{'path_myddir'}/relay-log.info");
3829
3830  run_master_init_script($tinfo);
3831}
3832
3833
3834sub do_before_start_slave ($) {
3835  my ($tinfo)= @_;
3836
3837  my $tname= $tinfo->{'name'};
3838  my $init_script= $tinfo->{'master_sh'};
3839
3840  # Don't delete anything if starting dirty
3841  return if ($opt_start_dirty);
3842
3843  foreach my $bin ( glob("$opt_vardir/log/slave*-bin*") )
3844  {
3845    unlink($bin);
3846  }
3847
3848  unlink("$slave->[0]->{'path_myddir'}/master.info");
3849  unlink("$slave->[0]->{'path_myddir'}/relay-log.info");
3850
3851  # Run slave initialization shell script if one exists
3852  if ( $init_script )
3853  {
3854    my $ret= mtr_run("/bin/sh", [$init_script], "", "", "", "");
3855    if ( $ret != 0 )
3856    {
3857      # FIXME rewrite those scripts to return 0 if successful
3858      # mtr_warning("$init_script exited with code $ret");
3859    }
3860  }
3861
3862  foreach my $bin ( glob("$slave->[0]->{'path_myddir'}/log.*") )
3863  {
3864    unlink($bin);
3865  }
3866}
3867
3868
3869sub mysqld_arguments ($$$$) {
3870  my $args=              shift;
3871  my $mysqld=            shift;
3872  my $extra_opt=         shift;
3873  my $slave_master_info= shift;
3874
3875  my $idx= $mysqld->{'idx'};
3876  my $sidx= "";                 # Index as string, 0 is empty string
3877  if ( $idx> 0 )
3878  {
3879    $sidx= $idx;
3880  }
3881
3882  my $prefix= "";               # If mysqltest server arg
3883  if ( $glob_use_embedded_server )
3884  {
3885    $prefix= "--server-arg=";
3886  }
3887
3888  mtr_add_arg($args, "%s--no-defaults", $prefix);
3889
3890  mtr_add_arg($args, "%s--basedir=%s", $prefix, $glob_basedir);
3891  mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir);
3892
3893  if ( $mysql_version_id >= 50036)
3894  {
3895    # By default, prevent the started mysqld to access files outside of vardir
3896    mtr_add_arg($args, "%s--secure-file-priv=%s", $prefix, $opt_vardir);
3897  }
3898
3899  if ( $mysql_version_id >= 50000 )
3900  {
3901    mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
3902  }
3903
3904  mtr_add_arg($args, "%s--character-set-server=latin1", $prefix);
3905  mtr_add_arg($args, "%s--lc-messages-dir=%s", $prefix, $path_language);
3906  mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
3907
3908  # Increase default connect_timeout to avoid intermittent
3909  # disconnects when test servers are put under load
3910  # see BUG#28359
3911  mtr_add_arg($args, "%s--connect-timeout=60", $prefix);
3912
3913
3914  # When mysqld is run by a root user(euid is 0), it will fail
3915  # to start unless we specify what user to run as, see BUG#30630
3916  my $euid= $>;
3917  if (!$glob_win32 and $euid == 0 and
3918      grep(/^--user/, @$extra_opt, @opt_extra_mysqld_opt) == 0) {
3919    mtr_add_arg($args, "%s--user=root", $prefix);
3920  }
3921
3922  if ( $opt_valgrind_mysqld )
3923  {
3924    if ( $mysql_version_id < 50100 )
3925    {
3926      mtr_add_arg($args, "%s--skip-bdb", $prefix);
3927    }
3928  }
3929
3930  mtr_add_arg($args, "%s--pid-file=%s", $prefix,
3931	      $mysqld->{'path_pid'});
3932
3933  mtr_add_arg($args, "%s--port=%d", $prefix,
3934                $mysqld->{'port'});
3935
3936  mtr_add_arg($args, "%s--socket=%s", $prefix,
3937	      $mysqld->{'path_sock'});
3938
3939  mtr_add_arg($args, "%s--datadir=%s", $prefix,
3940	      $mysqld->{'path_myddir'});
3941
3942
3943  if ( $mysql_version_id >= 50106 )
3944  {
3945    # Turn on logging to bothe tables and file
3946    mtr_add_arg($args, "%s--log-output=table,file", $prefix);
3947  }
3948
3949  my $log_base_path= "$opt_vardir/log/$mysqld->{'type'}$sidx";
3950
3951  mtr_add_arg($args, "%s--general-log", $prefix);
3952  mtr_add_arg($args, "%s--general-log-file=%s.log", $prefix, $log_base_path);
3953  mtr_add_arg($args, "%s--slow-query-log", $prefix);
3954  mtr_add_arg($args,
3955              "%s--slow-query-log-file=%s-slow.log", $prefix, $log_base_path);
3956  # Check if "extra_opt" contains --skip-log-bin
3957  my $skip_binlog= grep(/^--skip-log-bin/, @$extra_opt, @opt_extra_mysqld_opt);
3958  if ( $mysqld->{'type'} eq 'master' )
3959  {
3960    if (! ($opt_skip_master_binlog || $skip_binlog) )
3961    {
3962      mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
3963                  $opt_vardir, $sidx);
3964    }
3965
3966    mtr_add_arg($args, "%s--server-id=%d", $prefix,
3967	       $idx > 0 ? $idx + 101 : 1);
3968
3969    mtr_add_arg($args, "%s--loose-innodb_data_file_path=ibdata1:10M:autoextend",
3970		$prefix);
3971
3972    mtr_add_arg($args, "%s--local-infile", $prefix);
3973
3974    my $cluster= $clusters->[$mysqld->{'cluster'}];
3975    if ( $cluster->{'pid'} ||           # Cluster is started
3976	 $cluster->{'use_running'} )    # Using running cluster
3977    {
3978      mtr_add_arg($args, "%s--ndbcluster", $prefix);
3979      mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
3980		  $cluster->{'connect_string'});
3981      if ( $mysql_version_id >= 50100 )
3982      {
3983	mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
3984      }
3985    }
3986    else
3987    {
3988      mtr_add_arg($args, "%s--loose-skip-ndbcluster", $prefix);
3989    }
3990  }
3991  else
3992  {
3993    mtr_error("unknown mysqld type")
3994      unless $mysqld->{'type'} eq 'slave';
3995
3996    if (! ( $opt_skip_slave_binlog || $skip_binlog ))
3997    {
3998      mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix,
3999                  $opt_vardir, $sidx); # FIXME use own dir for binlogs
4000      mtr_add_arg($args, "%s--log-slave-updates", $prefix);
4001    }
4002
4003    mtr_add_arg($args, "%s--master-retry-count=10", $prefix);
4004
4005    mtr_add_arg($args, "%s--relay-log=%s/log/slave%s-relay-bin", $prefix,
4006                $opt_vardir, $sidx);
4007    mtr_add_arg($args, "%s--report-host=127.0.0.1", $prefix);
4008    mtr_add_arg($args, "%s--report-port=%d", $prefix,
4009                $mysqld->{'port'});
4010    mtr_add_arg($args, "%s--report-user=root", $prefix);
4011    mtr_add_arg($args, "%s--loose-skip-innodb", $prefix);
4012    mtr_add_arg($args, "%s--skip-slave-start", $prefix);
4013
4014    # Directory where slaves find the dumps generated by "load data"
4015    # on the server. The path need to have constant length otherwise
4016    # test results will vary, thus a relative path is used.
4017    my $slave_load_path= "../tmp";
4018    mtr_add_arg($args, "%s--slave-load-tmpdir=%s", $prefix,
4019                $slave_load_path);
4020    mtr_add_arg($args, "%s--slave_net_timeout=120", $prefix);
4021
4022    if ( @$slave_master_info )
4023    {
4024      foreach my $arg ( @$slave_master_info )
4025      {
4026        mtr_add_arg($args, "%s%s", $prefix, $arg);
4027      }
4028    }
4029    else
4030    {
4031#      NOTE: the backport (see BUG#48048) originally removed the
4032#            commented out lines below. However, given that they are
4033#            protected with a version check (< 50200) now, it should be
4034#            safe to keep them. The problem is that the backported patch
4035#            was into a 5.1 GA codebase - mysql-5.1-rep+2 tree - so
4036#            version is 501XX, consequently check becomes worthless. It
4037#            should be safe to uncomment them when merging up to 5.5.
4038#
4039#            RQG semisync test runs on the 5.1 GA tree and needs MTR v1.
4040#            This was causing the test to fail (slave would not start
4041#            due to unrecognized option(s)).
4042#      if ($mysql_version_id < 50200)
4043#      {
4044#        mtr_add_arg($args, "%s--master-user=root", $prefix);
4045#        mtr_add_arg($args, "%s--master-connect-retry=1", $prefix);
4046#        mtr_add_arg($args, "%s--master-host=127.0.0.1", $prefix);
4047#        mtr_add_arg($args, "%s--master-password=", $prefix);
4048#        mtr_add_arg($args, "%s--master-port=%d", $prefix,
4049#    	            $master->[0]->{'port'}); # First master
4050#      }
4051      my $slave_server_id=  2 + $idx;
4052      mtr_add_arg($args, "%s--server-id=%d", $prefix, $slave_server_id);
4053    }
4054
4055    my $cluster= $clusters->[$mysqld->{'cluster'}];
4056    if ( $cluster->{'pid'} ||         # Slave cluster is started
4057	 $cluster->{'use_running'} )  # Using running slave cluster
4058    {
4059      mtr_add_arg($args, "%s--ndbcluster", $prefix);
4060      mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
4061		  $cluster->{'connect_string'});
4062
4063      if ( $mysql_version_id >= 50100 )
4064      {
4065	mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
4066      }
4067    }
4068    else
4069    {
4070      mtr_add_arg($args, "%s--loose-skip-ndbcluster", $prefix);
4071    }
4072
4073  } # end slave
4074
4075  if ( $opt_debug )
4076  {
4077    mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/%s%s.trace",
4078		$prefix, $path_vardir_trace, $mysqld->{'type'}, $sidx);
4079  }
4080
4081  mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
4082  mtr_add_arg($args, "%s--sort_buffer_size=256K", $prefix);
4083  mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix);
4084
4085  if ( $opt_ssl_supported )
4086  {
4087    mtr_add_arg($args, "%s--ssl-ca=%s/std_data/cacert.pem", $prefix,
4088                $glob_mysql_test_dir);
4089    mtr_add_arg($args, "%s--ssl-cert=%s/std_data/server-cert.pem", $prefix,
4090                $glob_mysql_test_dir);
4091    mtr_add_arg($args, "%s--ssl-key=%s/std_data/server-key.pem", $prefix,
4092                $glob_mysql_test_dir);
4093  }
4094
4095  if ( $opt_warnings )
4096  {
4097    mtr_add_arg($args, "%s--log-warnings", $prefix);
4098  }
4099
4100  # Indicate to "mysqld" it will be debugged in debugger
4101  if ( $glob_debugger )
4102  {
4103    mtr_add_arg($args, "%s--gdb", $prefix);
4104  }
4105
4106  my $found_skip_core= 0;
4107  foreach my $arg ( @opt_extra_mysqld_opt, @$extra_opt )
4108  {
4109    # Allow --skip-core-file to be set in <testname>-[master|slave].opt file
4110    if ($arg eq "--skip-core-file")
4111    {
4112      $found_skip_core= 1;
4113    }
4114    elsif ($skip_binlog and mtr_match_prefix($arg, "--binlog-format"))
4115    {
4116      ; # Dont add --binlog-format when running without binlog
4117    }
4118    else
4119    {
4120      mtr_add_arg($args, "%s%s", $prefix, $arg);
4121    }
4122  }
4123  if ( !$found_skip_core )
4124  {
4125    mtr_add_arg($args, "%s%s", $prefix, "--core-file");
4126  }
4127
4128  if ( !$opt_bench and $mysqld->{'type'} eq 'master' )
4129  {
4130    mtr_add_arg($args, "%s--open-files-limit=1024", $prefix);
4131  }
4132
4133  return $args;
4134}
4135
4136
4137##############################################################################
4138#
4139#  Start mysqld and return the PID
4140#
4141##############################################################################
4142
4143sub mysqld_start ($$$) {
4144  my $mysqld=            shift;
4145  my $extra_opt=         shift;
4146  my $slave_master_info= shift;
4147
4148  my $args;                             # Arg vector
4149  my $exe;
4150  my $pid= -1;
4151  my $wait_for_pid_file= 1;
4152
4153  my $type= $mysqld->{'type'};
4154  my $idx= $mysqld->{'idx'};
4155
4156  mtr_error("Internal error: mysqld should never be started for embedded")
4157    if $glob_use_embedded_server;
4158
4159  if ( $type eq 'master' )
4160  {
4161    $exe= $exe_master_mysqld;
4162  }
4163  elsif ( $type eq 'slave' )
4164  {
4165    $exe= $exe_slave_mysqld;
4166  }
4167  else
4168  {
4169    mtr_error("Unknown 'type' \"$type\" passed to mysqld_start");
4170  }
4171
4172  mtr_init_args(\$args);
4173
4174  if ( $opt_valgrind_mysqld )
4175  {
4176    valgrind_arguments($args, \$exe);
4177  }
4178
4179  mysqld_arguments($args,$mysqld,$extra_opt,$slave_master_info);
4180
4181  if ( $opt_gdb || $opt_manual_gdb)
4182  {
4183    gdb_arguments(\$args, \$exe, "$type"."_$idx");
4184  }
4185  elsif ( $opt_ddd || $opt_manual_ddd )
4186  {
4187    ddd_arguments(\$args, \$exe, "$type"."_$idx");
4188  }
4189  elsif ( $opt_debugger )
4190  {
4191    debugger_arguments(\$args, \$exe, "$type"."_$idx");
4192  }
4193  elsif ( $opt_manual_debug )
4194  {
4195     print "\nStart $type in your debugger\n" .
4196           "dir: $glob_mysql_test_dir\n" .
4197           "exe: $exe\n" .
4198	   "args:  " . join(" ", @$args)  . "\n\n" .
4199	   "Waiting ....\n";
4200
4201     # Indicate the exe should not be started
4202    $exe= undef;
4203  }
4204  else
4205  {
4206    # Default to not wait until pid file has been created
4207    $wait_for_pid_file= 0;
4208  }
4209
4210  # Remove the pidfile
4211  unlink($mysqld->{'path_pid'});
4212
4213  if ( defined $exe )
4214  {
4215    $pid= mtr_spawn($exe, $args, "",
4216		    $mysqld->{'path_myerr'},
4217		    $mysqld->{'path_myerr'},
4218		    "",
4219		    { append_log_file => 1 });
4220  }
4221
4222
4223  if ( $wait_for_pid_file && !sleep_until_file_created($mysqld->{'path_pid'},
4224						       $mysqld->{'start_timeout'},
4225						       $pid))
4226  {
4227
4228    mtr_error("Failed to start mysqld $mysqld->{'type'}");
4229  }
4230
4231
4232  # Remember pid of the started process
4233  $mysqld->{'pid'}= $pid;
4234
4235  # Remember options used when starting
4236  $mysqld->{'start_opts'}= $extra_opt;
4237  $mysqld->{'start_slave_master_info'}= $slave_master_info;
4238
4239  mtr_verbose("mysqld pid: $pid");
4240  return $pid;
4241}
4242
4243
4244sub stop_all_servers () {
4245
4246  mtr_report("Stopping All Servers");
4247
4248  if ( ! $opt_skip_im )
4249  {
4250    mtr_report("Shutting-down Instance Manager");
4251    unless (mtr_im_stop($instance_manager, "stop_all_servers"))
4252    {
4253      mtr_error("Failed to stop Instance Manager.")
4254    }
4255  }
4256
4257  my %admin_pids; # hash of admin processes that requests shutdown
4258  my @kill_pids;  # list of processes to shutdown/kill
4259  my $pid;
4260
4261  # Start shutdown of all started masters
4262  foreach my $mysqld (@{$slave}, @{$master})
4263  {
4264    if ( $mysqld->{'pid'} )
4265    {
4266      $pid= mtr_mysqladmin_start($mysqld, "shutdown", 70);
4267      $admin_pids{$pid}= 1;
4268
4269      push(@kill_pids,{
4270		       pid      => $mysqld->{'pid'},
4271                       real_pid => $mysqld->{'real_pid'},
4272		       pidfile  => $mysqld->{'path_pid'},
4273		       sockfile => $mysqld->{'path_sock'},
4274		       port     => $mysqld->{'port'},
4275                       errfile  => $mysqld->{'path_myerr'},
4276		      });
4277
4278      $mysqld->{'pid'}= 0; # Assume we are done with it
4279    }
4280  }
4281
4282  # Start shutdown of clusters
4283  foreach my $cluster (@{$clusters})
4284  {
4285    if ( $cluster->{'pid'} )
4286    {
4287      $pid= mtr_ndbmgm_start($cluster, "shutdown");
4288      $admin_pids{$pid}= 1;
4289
4290      push(@kill_pids,{
4291		       pid      => $cluster->{'pid'},
4292		       pidfile  => $cluster->{'path_pid'}
4293		      });
4294
4295      $cluster->{'pid'}= 0; # Assume we are done with it
4296
4297      foreach my $ndbd (@{$cluster->{'ndbds'}})
4298      {
4299        if ( $ndbd->{'pid'} )
4300	{
4301	  push(@kill_pids,{
4302			   pid      => $ndbd->{'pid'},
4303			   pidfile  => $ndbd->{'path_pid'},
4304			  });
4305	  $ndbd->{'pid'}= 0;
4306	}
4307      }
4308    }
4309  }
4310
4311  # Wait blocking until all shutdown processes has completed
4312  mtr_wait_blocking(\%admin_pids);
4313
4314  # Make sure that process has shutdown else try to kill them
4315  mtr_check_stop_servers(\@kill_pids);
4316
4317  foreach my $mysqld (@{$master}, @{$slave})
4318  {
4319    rm_ndbcluster_tables($mysqld->{'path_myddir'});
4320  }
4321}
4322
4323
4324sub run_testcase_need_master_restart($)
4325{
4326  my ($tinfo)= @_;
4327
4328  # We try to find out if we are to restart the master(s)
4329  my $do_restart= 0;          # Assumes we don't have to
4330
4331  if ( $glob_use_embedded_server )
4332  {
4333    mtr_verbose("Never start or restart for embedded server");
4334    return $do_restart;
4335  }
4336  elsif ( $tinfo->{'master_sh'} )
4337  {
4338    $do_restart= 1;           # Always restart if script to run
4339    mtr_verbose("Restart master: Always restart if script to run");
4340  }
4341  if ( $tinfo->{'force_restart'} )
4342  {
4343    $do_restart= 1; # Always restart if --force-restart in -opt file
4344    mtr_verbose("Restart master: Restart forced with --force-restart");
4345  }
4346  elsif ( ! $opt_skip_ndbcluster and
4347	  !$tinfo->{'ndb_test'} and
4348	  $clusters->[0]->{'pid'} != 0 )
4349  {
4350    $do_restart= 1;           # Restart without cluster
4351    mtr_verbose("Restart master: Test does not need cluster");
4352  }
4353  elsif ( ! $opt_skip_ndbcluster and
4354	  $tinfo->{'ndb_test'} and
4355	  $clusters->[0]->{'pid'} == 0 )
4356  {
4357    $do_restart= 1;           # Restart with cluster
4358    mtr_verbose("Restart master: Test need cluster");
4359  }
4360  elsif( $tinfo->{'component_id'} eq 'im' )
4361  {
4362    $do_restart= 1;
4363    mtr_verbose("Restart master: Always restart for im tests");
4364  }
4365  elsif ( $master->[0]->{'running_master_options'} and
4366	  $master->[0]->{'running_master_options'}->{'timezone'} ne
4367	  $tinfo->{'timezone'})
4368  {
4369    $do_restart= 1;
4370    mtr_verbose("Restart master: Different timezone");
4371  }
4372  # Check that running master was started with same options
4373  # as the current test requires
4374  elsif (! mtr_same_opts($master->[0]->{'start_opts'},
4375                         $tinfo->{'master_opt'}) )
4376  {
4377    $do_restart= 1;
4378    mtr_verbose("Restart master: running with different options '" .
4379		join(" ", @{$tinfo->{'master_opt'}}) . "' != '" .
4380	  	join(" ", @{$master->[0]->{'start_opts'}}) . "'" );
4381  }
4382  elsif( ! $master->[0]->{'pid'} )
4383  {
4384    if ( $opt_extern )
4385    {
4386      $do_restart= 0;
4387      mtr_verbose("No restart: using extern master");
4388    }
4389    else
4390    {
4391      $do_restart= 1;
4392      mtr_verbose("Restart master: master is not started");
4393    }
4394  }
4395  return $do_restart;
4396}
4397
4398sub run_testcase_need_slave_restart($)
4399{
4400  my ($tinfo)= @_;
4401
4402  # We try to find out if we are to restart the slaves
4403  my $do_slave_restart= 0;     # Assumes we don't have to
4404
4405  if ( $glob_use_embedded_server )
4406  {
4407    mtr_verbose("Never start or restart for embedded server");
4408    return $do_slave_restart;
4409  }
4410  elsif ( $max_slave_num == 0)
4411  {
4412    mtr_verbose("Skip slave restart: No testcase use slaves");
4413  }
4414  else
4415  {
4416
4417    # Check if any slave is currently started
4418    my $any_slave_started= 0;
4419    foreach my $mysqld (@{$slave})
4420    {
4421      if ( $mysqld->{'pid'} )
4422      {
4423	$any_slave_started= 1;
4424	last;
4425      }
4426    }
4427
4428    if ($any_slave_started)
4429    {
4430      mtr_verbose("Restart slave: Slave is started, always restart");
4431      $do_slave_restart= 1;
4432    }
4433    elsif ( $tinfo->{'slave_num'} )
4434    {
4435      mtr_verbose("Restart slave: Test need slave");
4436      $do_slave_restart= 1;
4437    }
4438  }
4439
4440  return $do_slave_restart;
4441
4442}
4443
4444# ----------------------------------------------------------------------
4445# If not using a running servers we may need to stop and restart.
4446# We restart in the case we have initiation scripts, server options
4447# etc to run. But we also restart again after the test first restart
4448# and test is run, to get back to normal server settings.
4449#
4450# To make the code a bit more clean, we actually only stop servers
4451# here, and mark this to be done. Then a generic "start" part will
4452# start up the needed servers again.
4453# ----------------------------------------------------------------------
4454
4455sub run_testcase_stop_servers($$$) {
4456  my ($tinfo, $do_restart, $do_slave_restart)= @_;
4457  my $pid;
4458  my %admin_pids; # hash of admin processes that requests shutdown
4459  my @kill_pids;  # list of processes to shutdown/kill
4460
4461  # Remember if we restarted for this test case (count restarts)
4462  $tinfo->{'restarted'}= $do_restart;
4463
4464  if ( $do_restart )
4465  {
4466    delete $master->[0]->{'running_master_options'}; # Forget history
4467
4468    # Start shutdown of all started masters
4469    foreach my $mysqld (@{$master})
4470    {
4471      if ( $mysqld->{'pid'} )
4472      {
4473	$pid= mtr_mysqladmin_start($mysqld, "shutdown", 20);
4474
4475	$admin_pids{$pid}= 1;
4476
4477	push(@kill_pids,{
4478			 pid      => $mysqld->{'pid'},
4479			 real_pid => $mysqld->{'real_pid'},
4480			 pidfile  => $mysqld->{'path_pid'},
4481			 sockfile => $mysqld->{'path_sock'},
4482			 port     => $mysqld->{'port'},
4483			 errfile   => $mysqld->{'path_myerr'},
4484			});
4485
4486	$mysqld->{'pid'}= 0; # Assume we are done with it
4487      }
4488    }
4489
4490    # Start shutdown of master cluster
4491    my $cluster= $clusters->[0];
4492    if ( $cluster->{'pid'} )
4493    {
4494      $pid= mtr_ndbmgm_start($cluster, "shutdown");
4495      $admin_pids{$pid}= 1;
4496
4497      push(@kill_pids,{
4498		       pid      => $cluster->{'pid'},
4499		       pidfile  => $cluster->{'path_pid'}
4500		      });
4501
4502      $cluster->{'pid'}= 0; # Assume we are done with it
4503
4504      foreach my $ndbd (@{$cluster->{'ndbds'}})
4505      {
4506	push(@kill_pids,{
4507			 pid      => $ndbd->{'pid'},
4508			 pidfile  => $ndbd->{'path_pid'},
4509			});
4510	$ndbd->{'pid'}= 0; # Assume we are done with it
4511      }
4512    }
4513  }
4514
4515  if ( $do_restart || $do_slave_restart )
4516  {
4517
4518    delete $slave->[0]->{'running_slave_options'}; # Forget history
4519
4520    # Start shutdown of all started slaves
4521    foreach my $mysqld (@{$slave})
4522    {
4523      if ( $mysqld->{'pid'} )
4524      {
4525	$pid= mtr_mysqladmin_start($mysqld, "shutdown", 20);
4526
4527	$admin_pids{$pid}= 1;
4528
4529	push(@kill_pids,{
4530			 pid      => $mysqld->{'pid'},
4531			 real_pid => $mysqld->{'real_pid'},
4532			 pidfile  => $mysqld->{'path_pid'},
4533			 sockfile => $mysqld->{'path_sock'},
4534			 port     => $mysqld->{'port'},
4535			 errfile   => $mysqld->{'path_myerr'},
4536			});
4537
4538
4539	$mysqld->{'pid'}= 0; # Assume we are done with it
4540      }
4541    }
4542
4543    # Start shutdown of slave cluster
4544    my $cluster= $clusters->[1];
4545    if ( $cluster->{'pid'} )
4546    {
4547      $pid= mtr_ndbmgm_start($cluster, "shutdown");
4548
4549      $admin_pids{$pid}= 1;
4550
4551      push(@kill_pids,{
4552		       pid      => $cluster->{'pid'},
4553		       pidfile  => $cluster->{'path_pid'}
4554		      });
4555
4556      $cluster->{'pid'}= 0; # Assume we are done with it
4557
4558      foreach my $ndbd (@{$cluster->{'ndbds'}} )
4559      {
4560	push(@kill_pids,{
4561			 pid      => $ndbd->{'pid'},
4562			 pidfile  => $ndbd->{'path_pid'},
4563			});
4564	$ndbd->{'pid'}= 0; # Assume we are done with it
4565      }
4566    }
4567  }
4568
4569  # ----------------------------------------------------------------------
4570  # Shutdown has now been started and lists for the shutdown processes
4571  # and the processes to be killed has been created
4572  # ----------------------------------------------------------------------
4573
4574  # Wait blocking until all shutdown processes has completed
4575  mtr_wait_blocking(\%admin_pids);
4576
4577
4578  # Make sure that process has shutdown else try to kill them
4579  mtr_check_stop_servers(\@kill_pids);
4580
4581  foreach my $mysqld (@{$master}, @{$slave})
4582  {
4583    if ( ! $mysqld->{'pid'} )
4584    {
4585      # Remove ndbcluster tables if server is stopped
4586      rm_ndbcluster_tables($mysqld->{'path_myddir'});
4587    }
4588  }
4589}
4590
4591
4592#
4593# run_testcase_start_servers
4594#
4595# Start the servers needed by this test case
4596#
4597# RETURN
4598#  0 OK
4599#  1 Start failed
4600#
4601
4602sub run_testcase_start_servers($) {
4603  my $tinfo= shift;
4604  my $tname= $tinfo->{'name'};
4605
4606  if ( $tinfo->{'component_id'} eq 'mysqld' )
4607  {
4608    if ( ! $opt_skip_ndbcluster and
4609	 !$clusters->[0]->{'pid'} and
4610	 $tinfo->{'ndb_test'} )
4611    {
4612      # Test need cluster, cluster is not started, start it
4613      ndbcluster_start($clusters->[0], "");
4614    }
4615
4616    if ( !$master->[0]->{'pid'} )
4617    {
4618      # Master mysqld is not started
4619      do_before_start_master($tinfo);
4620
4621      mysqld_start($master->[0],$tinfo->{'master_opt'},[]);
4622
4623    }
4624
4625    if ( $clusters->[0]->{'pid'} || $clusters->[0]->{'use_running'}
4626	 and ! $master->[1]->{'pid'} and
4627	 $tinfo->{'master_num'} > 1 )
4628    {
4629      # Test needs cluster, start an extra mysqld connected to cluster
4630
4631      if ( $mysql_version_id >= 50100 )
4632      {
4633	# First wait for first mysql server to have created ndb system
4634	# tables ok FIXME This is a workaround so that only one mysqld
4635	# create the tables
4636	if ( ! sleep_until_file_created(
4637		  "$master->[0]->{'path_myddir'}/mysql/ndb_apply_status.ndb",
4638					$master->[0]->{'start_timeout'},
4639					$master->[0]->{'pid'}))
4640	{
4641
4642	  $tinfo->{'comment'}= "Failed to create 'mysql/ndb_apply_status' table";
4643	  return 1;
4644	}
4645      }
4646      mysqld_start($master->[1],$tinfo->{'master_opt'},[]);
4647    }
4648
4649    # Save this test case information, so next can examine it
4650    $master->[0]->{'running_master_options'}= $tinfo;
4651  }
4652  elsif ( ! $opt_skip_im and $tinfo->{'component_id'} eq 'im' )
4653  {
4654    # We have to create defaults file every time, in order to ensure that it
4655    # will be the same for each test. The problem is that test can change the
4656    # file (by SET/UNSET commands), so w/o recreating the file, execution of
4657    # one test can affect the other.
4658
4659    im_create_defaults_file($instance_manager);
4660
4661    if  ( ! mtr_im_start($instance_manager, $tinfo->{im_opts}) )
4662    {
4663      $tinfo->{'comment'}= "Failed to start Instance Manager. ";
4664      return 1;
4665    }
4666  }
4667
4668  # ----------------------------------------------------------------------
4669  # Start slaves - if needed
4670  # ----------------------------------------------------------------------
4671  if ( $tinfo->{'slave_num'} )
4672  {
4673    restore_slave_databases($tinfo->{'slave_num'});
4674
4675    do_before_start_slave($tinfo);
4676
4677    if ( ! $opt_skip_ndbcluster_slave and
4678	 !$clusters->[1]->{'pid'} and
4679	 $tinfo->{'ndb_test'} )
4680    {
4681      # Test need slave cluster, cluster is not started, start it
4682      ndbcluster_start($clusters->[1], "");
4683    }
4684
4685    for ( my $idx= 0; $idx <  $tinfo->{'slave_num'}; $idx++ )
4686    {
4687      if ( ! $slave->[$idx]->{'pid'} )
4688      {
4689	mysqld_start($slave->[$idx],$tinfo->{'slave_opt'},
4690		     $tinfo->{'slave_mi'});
4691
4692      }
4693    }
4694
4695    # Save this test case information, so next can examine it
4696    $slave->[0]->{'running_slave_options'}= $tinfo;
4697  }
4698
4699  # Wait for clusters to start
4700  foreach my $cluster (@{$clusters})
4701  {
4702
4703    next if !$cluster->{'pid'};
4704
4705    if (ndbcluster_wait_started($cluster, ""))
4706    {
4707      # failed to start
4708      $tinfo->{'comment'}= "Start of $cluster->{'name'} cluster failed";
4709      return 1;
4710    }
4711  }
4712
4713  # Wait for mysqld's to start
4714  foreach my $mysqld (@{$master},@{$slave})
4715  {
4716
4717    next if !$mysqld->{'pid'};
4718
4719    if (mysqld_wait_started($mysqld))
4720    {
4721      # failed to start
4722      $tinfo->{'comment'}=
4723	"Failed to start $mysqld->{'type'} mysqld $mysqld->{'idx'}";
4724      return 1;
4725    }
4726  }
4727  return 0;
4728}
4729
4730#
4731# Run include/check-testcase.test
4732# Before a testcase, run in record mode, save result file to var
4733# After testcase, run and compare with the recorded file, they should be equal!
4734#
4735# RETURN VALUE
4736#  0 OK
4737#  1 Check failed
4738#
4739sub run_check_testcase ($$) {
4740
4741  my $mode=     shift;
4742  my $mysqld=   shift;
4743
4744  my $name= "check-" . $mysqld->{'type'} . $mysqld->{'idx'};
4745
4746  my $args;
4747  mtr_init_args(\$args);
4748
4749  mtr_add_arg($args, "--no-defaults");
4750  mtr_add_arg($args, "--silent");
4751  mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
4752  mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
4753
4754  mtr_add_arg($args, "--socket=%s", $mysqld->{'path_sock'});
4755  mtr_add_arg($args, "--port=%d", $mysqld->{'port'});
4756  mtr_add_arg($args, "--database=test");
4757  mtr_add_arg($args, "--user=%s", $opt_user);
4758  mtr_add_arg($args, "--password=");
4759
4760  mtr_add_arg($args, "-R");
4761  mtr_add_arg($args, "$opt_vardir/tmp/$name.result");
4762
4763  if ( $mode eq "before" )
4764  {
4765    mtr_add_arg($args, "--record");
4766  }
4767
4768  my $res = mtr_run_test($exe_mysqltest,$args,
4769	        "include/check-testcase.test", "", "", "");
4770
4771  if ( $res == 1  and $mode eq "after")
4772  {
4773    mtr_run("diff",["-u",
4774		    "$opt_vardir/tmp/$name.result",
4775		    "$opt_vardir/tmp/$name.reject"],
4776	    "", "", "", "");
4777  }
4778  elsif ( $res )
4779  {
4780    mtr_error("Could not execute 'check-testcase' $mode testcase");
4781  }
4782  return $res;
4783}
4784
4785##############################################################################
4786#
4787#  Report the features that were compiled in
4788#
4789##############################################################################
4790
4791sub run_report_features () {
4792  my $args;
4793
4794  if ( ! $glob_use_embedded_server )
4795  {
4796    mysqld_start($master->[0],[],[]);
4797    if ( ! $master->[0]->{'pid'} )
4798    {
4799      mtr_error("Can't start the mysqld server");
4800    }
4801    mysqld_wait_started($master->[0]);
4802  }
4803
4804  my $tinfo = {};
4805  $tinfo->{'name'} = 'report features';
4806  $tinfo->{'result_file'} = undef;
4807  $tinfo->{'component_id'} = 'mysqld';
4808  $tinfo->{'path'} = 'include/report-features.test';
4809  $tinfo->{'timezone'}=  "GMT-3";
4810  $tinfo->{'slave_num'} = 0;
4811  $tinfo->{'master_opt'} = [];
4812  $tinfo->{'slave_opt'} = [];
4813  $tinfo->{'slave_mi'} = [];
4814  $tinfo->{'comment'} = 'report server features';
4815  run_mysqltest($tinfo);
4816
4817  if ( ! $glob_use_embedded_server )
4818  {
4819    stop_all_servers();
4820  }
4821}
4822
4823
4824sub run_mysqltest ($) {
4825  my ($tinfo)= @_;
4826  my $exe= $exe_mysqltest;
4827  my $args;
4828
4829  mtr_init_args(\$args);
4830
4831  mtr_add_arg($args, "--no-defaults");
4832  mtr_add_arg($args, "--silent");
4833  mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
4834  mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
4835  mtr_add_arg($args, "--logdir=%s/log", $opt_vardir);
4836
4837  # Log line number and time  for each line in .test file
4838  mtr_add_arg($args, "--mark-progress")
4839    if $opt_mark_progress;
4840
4841  if ($tinfo->{'component_id'} eq 'im')
4842  {
4843    mtr_add_arg($args, "--socket=%s", $instance_manager->{'path_sock'});
4844    mtr_add_arg($args, "--port=%d", $instance_manager->{'port'});
4845    mtr_add_arg($args, "--user=%s", $instance_manager->{'admin_login'});
4846    mtr_add_arg($args, "--password=%s", $instance_manager->{'admin_password'});
4847  }
4848  else # component_id == mysqld
4849  {
4850    mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'});
4851    mtr_add_arg($args, "--port=%d", $master->[0]->{'port'});
4852    mtr_add_arg($args, "--database=test");
4853    mtr_add_arg($args, "--user=%s", $opt_user);
4854    mtr_add_arg($args, "--password=");
4855  }
4856
4857  if ( $opt_ps_protocol )
4858  {
4859    mtr_add_arg($args, "--ps-protocol");
4860  }
4861
4862  if ( $opt_sp_protocol )
4863  {
4864    mtr_add_arg($args, "--sp-protocol");
4865  }
4866
4867  if ( $opt_view_protocol )
4868  {
4869    mtr_add_arg($args, "--view-protocol");
4870  }
4871
4872  if ( $opt_cursor_protocol )
4873  {
4874    mtr_add_arg($args, "--cursor-protocol");
4875  }
4876
4877  if ( $opt_strace_client )
4878  {
4879    $exe=  "strace";            # FIXME there are ktrace, ....
4880    mtr_add_arg($args, "-o");
4881    mtr_add_arg($args, "%s/log/mysqltest.strace", $opt_vardir);
4882    mtr_add_arg($args, "$exe_mysqltest");
4883  }
4884
4885  if ( $opt_timer )
4886  {
4887    mtr_add_arg($args, "--timer-file=%s/log/timer", $opt_vardir);
4888  }
4889
4890  if ( $opt_compress )
4891  {
4892    mtr_add_arg($args, "--compress");
4893  }
4894
4895  if ( $opt_sleep )
4896  {
4897    mtr_add_arg($args, "--sleep=%d", $opt_sleep);
4898  }
4899
4900  if ( $opt_debug )
4901  {
4902    mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace",
4903		$path_vardir_trace);
4904  }
4905
4906  if ( $opt_ssl_supported )
4907  {
4908    mtr_add_arg($args, "--ssl-ca=%s/std_data/cacert.pem",
4909	        $glob_mysql_test_dir);
4910    mtr_add_arg($args, "--ssl-cert=%s/std_data/client-cert.pem",
4911	        $glob_mysql_test_dir);
4912    mtr_add_arg($args, "--ssl-key=%s/std_data/client-key.pem",
4913	        $glob_mysql_test_dir);
4914  }
4915
4916  if ( $opt_ssl )
4917  {
4918    # Turn on SSL for _all_ test cases if option --ssl was used
4919    mtr_add_arg($args, "--ssl");
4920  }
4921  elsif ( $opt_ssl_supported )
4922  {
4923    mtr_add_arg($args, "--skip-ssl");
4924  }
4925
4926  # ----------------------------------------------------------------------
4927  # If embedded server, we create server args to give mysqltest to pass on
4928  # ----------------------------------------------------------------------
4929
4930  if ( $glob_use_embedded_server )
4931  {
4932    mysqld_arguments($args,$master->[0],$tinfo->{'master_opt'},[]);
4933  }
4934
4935  # ----------------------------------------------------------------------
4936  # export MYSQL_TEST variable containing <path>/mysqltest <args>
4937  # ----------------------------------------------------------------------
4938  $ENV{'MYSQL_TEST'}=
4939    mtr_native_path($exe_mysqltest) . " " . join(" ", @$args);
4940
4941  # ----------------------------------------------------------------------
4942  # Add arguments that should not go into the MYSQL_TEST env var
4943  # ----------------------------------------------------------------------
4944
4945  if ( $opt_valgrind_mysqltest )
4946  {
4947    # Prefix the Valgrind options to the argument list.
4948    # We do this here, since we do not want to Valgrind the nested invocations
4949    # of mysqltest; that would mess up the stderr output causing test failure.
4950    my @args_saved = @$args;
4951    mtr_init_args(\$args);
4952    valgrind_arguments($args, \$exe);
4953    mtr_add_arg($args, "%s", $_) for @args_saved;
4954  }
4955
4956  mtr_add_arg($args, "--test-file=%s", $tinfo->{'path'});
4957
4958  # Number of lines of resut to include in failure report
4959  mtr_add_arg($args, "--tail-lines=20");
4960
4961  if ( defined $tinfo->{'result_file'} ) {
4962    mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'});
4963  }
4964
4965  if ( $opt_record )
4966  {
4967    mtr_add_arg($args, "--record");
4968  }
4969
4970  if ( $opt_client_gdb )
4971  {
4972    gdb_arguments(\$args, \$exe, "client");
4973  }
4974  elsif ( $opt_client_ddd )
4975  {
4976    ddd_arguments(\$args, \$exe, "client");
4977  }
4978  elsif ( $opt_client_debugger )
4979  {
4980    debugger_arguments(\$args, \$exe, "client");
4981  }
4982
4983  if ( $opt_check_testcases )
4984  {
4985    foreach my $mysqld (@{$master}, @{$slave})
4986    {
4987      if ($mysqld->{'pid'})
4988      {
4989	run_check_testcase("before", $mysqld);
4990      }
4991    }
4992  }
4993
4994  my $res = mtr_run_test($exe,$args,"","",$path_timefile,"");
4995
4996  if ( $opt_check_testcases )
4997  {
4998    foreach my $mysqld (@{$master}, @{$slave})
4999    {
5000      if ($mysqld->{'pid'})
5001      {
5002	if (run_check_testcase("after", $mysqld))
5003	{
5004	  # Check failed, mark the test case with that info
5005	  $tinfo->{'check_testcase_failed'}= 1;
5006	}
5007      }
5008    }
5009  }
5010
5011  return $res;
5012
5013}
5014
5015
5016#
5017# Modify the exe and args so that program is run in gdb in xterm
5018#
5019sub gdb_arguments {
5020  my $args= shift;
5021  my $exe=  shift;
5022  my $type= shift;
5023
5024  # Write $args to gdb init file
5025  my $str= join(" ", @$$args);
5026  my $gdb_init_file= "$opt_tmpdir/gdbinit.$type";
5027
5028  # Remove the old gdbinit file
5029  unlink($gdb_init_file);
5030
5031  if ( $type eq "client" )
5032  {
5033    # write init file for client
5034    mtr_tofile($gdb_init_file,
5035	       "set args $str\n" .
5036	       "break main\n");
5037  }
5038  else
5039  {
5040    # write init file for mysqld
5041    mtr_tofile($gdb_init_file,
5042	       "set args $str\n" .
5043	       "break mysql_parse\n" .
5044	       "commands 1\n" .
5045	       "disable 1\n" .
5046	       "end\n" .
5047	       "run");
5048  }
5049
5050  if ( $opt_manual_gdb )
5051  {
5052     print "\nTo start gdb for $type, type in another window:\n";
5053     print "gdb -cd $glob_mysql_test_dir -x $gdb_init_file $$exe\n";
5054
5055     # Indicate the exe should not be started
5056     $$exe= undef;
5057     return;
5058  }
5059
5060  $$args= [];
5061  mtr_add_arg($$args, "-title");
5062  mtr_add_arg($$args, "$type");
5063  mtr_add_arg($$args, "-e");
5064
5065  if ( $exe_libtool )
5066  {
5067    mtr_add_arg($$args, $exe_libtool);
5068    mtr_add_arg($$args, "--mode=execute");
5069  }
5070
5071  mtr_add_arg($$args, "gdb");
5072  mtr_add_arg($$args, "-x");
5073  mtr_add_arg($$args, "$gdb_init_file");
5074  mtr_add_arg($$args, "$$exe");
5075
5076  $$exe= "xterm";
5077}
5078
5079
5080#
5081# Modify the exe and args so that program is run in ddd
5082#
5083sub ddd_arguments {
5084  my $args= shift;
5085  my $exe=  shift;
5086  my $type= shift;
5087
5088  # Write $args to ddd init file
5089  my $str= join(" ", @$$args);
5090  my $gdb_init_file= "$opt_tmpdir/gdbinit.$type";
5091
5092  # Remove the old gdbinit file
5093  unlink($gdb_init_file);
5094
5095  if ( $type eq "client" )
5096  {
5097    # write init file for client
5098    mtr_tofile($gdb_init_file,
5099	       "set args $str\n" .
5100	       "break main\n");
5101  }
5102  else
5103  {
5104    # write init file for mysqld
5105    mtr_tofile($gdb_init_file,
5106	       "file $$exe\n" .
5107	       "set args $str\n" .
5108	       "break mysql_parse\n" .
5109	       "commands 1\n" .
5110	       "disable 1\n" .
5111	       "end");
5112  }
5113
5114  if ( $opt_manual_ddd )
5115  {
5116     print "\nTo start ddd for $type, type in another window:\n";
5117     print "ddd -cd $glob_mysql_test_dir -x $gdb_init_file $$exe\n";
5118
5119     # Indicate the exe should not be started
5120     $$exe= undef;
5121     return;
5122  }
5123
5124  my $save_exe= $$exe;
5125  $$args= [];
5126  if ( $exe_libtool )
5127  {
5128    $$exe= $exe_libtool;
5129    mtr_add_arg($$args, "--mode=execute");
5130    mtr_add_arg($$args, "ddd");
5131  }
5132  else
5133  {
5134    $$exe= "ddd";
5135  }
5136  mtr_add_arg($$args, "--command=$gdb_init_file");
5137  mtr_add_arg($$args, "$save_exe");
5138}
5139
5140
5141#
5142# Modify the exe and args so that program is run in the selected debugger
5143#
5144sub debugger_arguments {
5145  my $args= shift;
5146  my $exe=  shift;
5147  my $debugger= $opt_debugger || $opt_client_debugger;
5148
5149  if ( $debugger =~ /vcexpress|vc|devenv/ )
5150  {
5151    # vc[express] /debugexe exe arg1 .. argn
5152
5153    # Add /debugexe and name of the exe before args
5154    unshift(@$$args, "/debugexe");
5155    unshift(@$$args, "$$exe");
5156
5157    # Set exe to debuggername
5158    $$exe= $debugger;
5159
5160  }
5161  elsif ( $debugger =~ /windbg/ )
5162  {
5163    # windbg exe arg1 .. argn
5164
5165    # Add name of the exe before args
5166    unshift(@$$args, "$$exe");
5167
5168    # Set exe to debuggername
5169    $$exe= $debugger;
5170
5171  }
5172  elsif ( $debugger eq "dbx" )
5173  {
5174    # xterm -e dbx -r exe arg1 .. argn
5175
5176    unshift(@$$args, $$exe);
5177    unshift(@$$args, "-r");
5178    unshift(@$$args, $debugger);
5179    unshift(@$$args, "-e");
5180
5181    $$exe= "xterm";
5182
5183  }
5184  else
5185  {
5186    mtr_error("Unknown argument \"$debugger\" passed to --debugger");
5187  }
5188}
5189
5190
5191#
5192# Modify the exe and args so that program is run in valgrind
5193#
5194sub valgrind_arguments {
5195  my $args= shift;
5196  my $exe=  shift;
5197
5198  if ( $opt_callgrind)
5199  {
5200    mtr_add_arg($args, "--tool=callgrind");
5201    mtr_add_arg($args, "--base=$opt_vardir/log");
5202  }
5203  else
5204  {
5205    mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
5206    mtr_add_arg($args, "--leak-check=yes");
5207    mtr_add_arg($args, "--num-callers=16");
5208    mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)
5209      if -f "$glob_mysql_test_dir/valgrind.supp";
5210  }
5211
5212  # Add valgrind options, can be overriden by user
5213  mtr_add_arg($args, '%s', $_) for (@valgrind_args);
5214
5215  mtr_add_arg($args, $$exe);
5216
5217  $$exe= $opt_valgrind_path || "valgrind";
5218
5219  if ($exe_libtool)
5220  {
5221    # Add "libtool --mode-execute" before the test to execute
5222    # if running in valgrind(to avoid valgrinding bash)
5223    unshift(@$args, "--mode=execute", $$exe);
5224    $$exe= $exe_libtool;
5225  }
5226}
5227
5228
5229##############################################################################
5230#
5231#  Usage
5232#
5233##############################################################################
5234
5235sub usage ($) {
5236  my $message= shift;
5237
5238  if ( $message )
5239  {
5240    print STDERR "$message\n";
5241  }
5242
5243  print <<HERE;
5244
5245$0 [ OPTIONS ] [ TESTCASE ]
5246
5247Options to control what engine/variation to run
5248
5249  embedded-server       Use the embedded server, i.e. no mysqld daemons
5250  ps-protocol           Use the binary protocol between client and server
5251  cursor-protocol       Use the cursor protocol between client and server
5252                        (implies --ps-protocol)
5253  view-protocol         Create a view to execute all non updating queries
5254  sp-protocol           Create a stored procedure to execute all queries
5255  compress              Use the compressed protocol between client and server
5256  ssl                   Use ssl protocol between client and server
5257  skip-ssl              Dont start server with support for ssl connections
5258  bench                 Run the benchmark suite
5259  small-bench           Run the benchmarks with --small-tests --small-tables
5260  ndb|with-ndbcluster   Use cluster as default table type
5261  vs-config             Visual Studio configuration used to create executables
5262                        (default: MTR_VS_CONFIG environment variable)
5263
5264Options to control directories to use
5265  benchdir=DIR          The directory where the benchmark suite is stored
5266                        (default: ../../mysql-bench)
5267  tmpdir=DIR            The directory where temporary files are stored
5268                        (default: ./var/tmp).
5269  vardir=DIR            The directory where files generated from the test run
5270                        is stored (default: ./var). Specifying a ramdisk or
5271                        tmpfs will speed up tests.
5272  mem                   Run testsuite in "memory" using tmpfs or ramdisk
5273                        Attempts to find a suitable location
5274                        using a builtin list of standard locations
5275                        for tmpfs (/dev/shm)
5276                        The option can also be set using environment
5277                        variable MTR_MEM=[DIR]
5278
5279Options to control what test suites or cases to run
5280
5281  force                 Continue to run the suite after failure
5282  with-ndbcluster-only  Run only tests that include "ndb" in the filename
5283  skip-ndb[cluster]     Skip all tests that need cluster
5284  skip-ndb[cluster]-slave Skip all tests that need a slave cluster
5285  ndb-extra             Run extra tests from ndb directory
5286  do-test=PREFIX or REGEX
5287                        Run test cases which name are prefixed with PREFIX
5288                        or fulfills REGEX
5289  skip-test=PREFIX or REGEX
5290                        Skip test cases which name are prefixed with PREFIX
5291                        or fulfills REGEX
5292  start-from=PREFIX     Run test cases starting from test prefixed with PREFIX
5293  suite[s]=NAME1,..,NAMEN Collect tests in suites from the comma separated
5294                        list of suite names.
5295                        The default is: "$opt_suites_default"
5296  skip-rpl              Skip the replication test cases.
5297  skip-im               Don't start IM, and skip the IM test cases
5298  big-test              Set the environment variable BIG_TEST, which can be
5299                        checked from test cases.
5300  combination="ARG1 .. ARG2" Specify a set of "mysqld" arguments for one
5301                        combination.
5302  skip-combination      Skip any combination options and combinations files
5303
5304Options that specify ports
5305
5306  master_port=PORT      Specify the port number used by the first master
5307  slave_port=PORT       Specify the port number used by the first slave
5308  ndbcluster-port=PORT  Specify the port number used by cluster
5309  ndbcluster-port-slave=PORT  Specify the port number used by slave cluster
5310  mtr-build-thread=#    Specify unique collection of ports. Can also be set by
5311                        setting the environment variable MTR_BUILD_THREAD.
5312
5313Options for test case authoring
5314
5315  record TESTNAME       (Re)genereate the result file for TESTNAME
5316  check-testcases       Check testcases for sideeffects
5317  mark-progress         Log line number and elapsed time to <testname>.progress
5318
5319Options that pass on options
5320
5321  mysqld=ARGS           Specify additional arguments to "mysqld"
5322
5323Options to run test on running server
5324
5325  extern                Use running server for tests
5326  ndb-connectstring=STR Use running cluster, and connect using STR
5327  ndb-connectstring-slave=STR Use running slave cluster, and connect using STR
5328  user=USER             User for connection to extern server
5329  socket=PATH           Socket for connection to extern server
5330
5331Options for debugging the product
5332
5333  client-ddd            Start mysqltest client in ddd
5334  client-debugger=NAME  Start mysqltest in the selected debugger
5335  client-gdb            Start mysqltest client in gdb
5336  ddd                   Start mysqld in ddd
5337  debug                 Dump trace output for all servers and client programs
5338  debugger=NAME         Start mysqld in the selected debugger
5339  gdb                   Start the mysqld(s) in gdb
5340  manual-debug          Let user manually start mysqld in debugger, before
5341                        running test(s)
5342  manual-gdb            Let user manually start mysqld in gdb, before running
5343                        test(s)
5344  manual-ddd            Let user manually start mysqld in ddd, before running
5345                        test(s)
5346  master-binary=PATH    Specify the master "mysqld" to use
5347  slave-binary=PATH     Specify the slave "mysqld" to use
5348  strace-client         Create strace output for mysqltest client
5349  max-save-core         Limit the number of core files saved (to avoid filling
5350                        up disks for heavily crashing server). Defaults to
5351                        $opt_max_save_core, set to 0 for no limit.
5352
5353Options for coverage, profiling etc
5354
5355  gcov                  FIXME
5356  gprof                 FIXME
5357  valgrind              Run the "mysqltest" and "mysqld" executables using
5358                        valgrind with default options
5359  valgrind-all          Synonym for --valgrind
5360  valgrind-mysqltest    Run the "mysqltest" and "mysql_client_test" executable
5361                        with valgrind
5362  valgrind-mysqld       Run the "mysqld" executable with valgrind
5363  valgrind-options=ARGS Deprecated, use --valgrind-option
5364  valgrind-option=ARGS  Option to give valgrind, replaces default option(s),
5365                        can be specified more then once
5366  valgrind-path=[EXE]   Path to the valgrind executable
5367  callgrind             Instruct valgrind to use callgrind
5368
5369Misc options
5370
5371  comment=STR           Write STR to the output
5372  notimer               Don't show test case execution time
5373  script-debug          Debug this script itself
5374  verbose               More verbose output
5375  start-and-exit        Only initialize and start the servers, using the
5376                        startup settings for the specified test case (if any)
5377  start-dirty           Only start the servers (without initialization) for
5378                        the specified test case (if any)
5379  fast                  Don't try to clean up from earlier runs
5380  reorder               Reorder tests to get fewer server restarts
5381  help                  Get this help text
5382
5383  testcase-timeout=MINUTES Max test case run time (default $default_testcase_timeout)
5384  suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout)
5385  warnings | log-warnings Pass --log-warnings to mysqld
5386
5387  sleep=SECONDS         Passed to mysqltest, will be used as fixed sleep time
5388  client-bindir=PATH    Path to the directory where client binaries are located
5389  client-libdir=PATH    Path to the directory where client libraries are located
5390
5391Deprecated options
5392  with-openssl          Deprecated option for ssl
5393
5394
5395HERE
5396  mtr_exit(1);
5397
5398}
5399