#!/usr/bin/perl # Copyright (c) 2010,2011 Oracle and/or its affiliates. All rights reserved. # Use is subject to license terms. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA #################### FOR THE MOMENT THIS SCRIPT IS FOR TESTING PURPOSES use lib 'lib'; use lib "$ENV{RQG_HOME}/lib"; use Carp; use strict; use GenTest; use GenTest::Constants; use GenTest::Properties; use GenTest::App::GenTest; use DBServer::DBServer; use DBServer::MySQL::MySQLd; use DBServer::MySQL::ReplMySQLd; $| = 1; if (osWindows()) { $SIG{CHLD} = "IGNORE"; } if (defined $ENV{RQG_HOME}) { if (osWindows()) { $ENV{RQG_HOME} = $ENV{RQG_HOME}.'\\'; } else { $ENV{RQG_HOME} = $ENV{RQG_HOME}.'/'; } } use Getopt::Long; use GenTest::Constants; use DBI; use Cwd; my $database = 'test'; my @dsns; my ($gendata, @basedirs, @mysqld_options, @vardirs, $rpl_mode, $engine, $help, $debug, @validators, @reporters, @transformers, $grammar_file, $redefine_file, $seed, $mask, $mask_level, $mem, $rows, $varchar_len, $xml_output, $valgrind, @valgrind_options, $views, $start_dirty, $filter, $build_thread, $sqltrace, $testname, $report_xml_tt, $report_xml_tt_type, $report_xml_tt_dest, $notnull, $querytimeout); my $gendata=''; ## default simple gendata my $threads = my $default_threads = 10; my $queries = my $default_queries = 1000; my $duration = my $default_duration = 3600; my @ARGV_saved = @ARGV; my $opt_result = GetOptions( 'mysqld=s@' => \$mysqld_options[0], 'mysqld1=s@' => \$mysqld_options[0], 'mysqld2=s@' => \$mysqld_options[1], 'basedir=s' => \$basedirs[0], 'basedir1=s' => \$basedirs[0], 'basedir2=s' => \$basedirs[1], #'basedir=s@' => \@basedirs, 'vardir=s' => \$vardirs[0], 'vardir1=s' => \$vardirs[0], 'vardir2=s' => \$vardirs[1], #'vardir=s@' => \@vardirs, 'rpl_mode=s' => \$rpl_mode, 'engine=s' => \$engine, 'grammar=s' => \$grammar_file, 'redefine=s' => \$redefine_file, 'threads=i' => \$threads, 'queries=s' => \$queries, 'duration=i' => \$duration, 'help' => \$help, 'debug' => \$debug, 'validators=s@' => \@validators, 'reporters=s@' => \@reporters, 'transformers=s@' => \@transformers, 'gendata:s' => \$gendata, 'notnull' => \$notnull, 'seed=s' => \$seed, 'mask=i' => \$mask, 'mask-level=i' => \$mask_level, 'mem' => \$mem, 'rows=i' => \$rows, 'varchar-length=i' => \$varchar_len, 'xml-output=s' => \$xml_output, 'report-xml-tt' => \$report_xml_tt, 'report-xml-tt-type=s' => \$report_xml_tt_type, 'report-xml-tt-dest=s' => \$report_xml_tt_dest, 'testname=s' => \$testname, 'valgrind!' => \$valgrind, 'valgrind_options=s@' => \@valgrind_options, 'views' => \$views, 'start-dirty' => \$start_dirty, 'filter=s' => \$filter, 'mtr-build-thread=i' => \$build_thread, 'sqltrace' => \$sqltrace, 'querytimeout=i' => \$querytimeout ); if (!$opt_result || $help || $basedirs[0] eq '' || not defined $grammar_file) { help(); exit($help ? 0 : 1); } say("Copyright (c) 2010,2011 Oracle and/or its affiliates. All rights reserved. Use is subject to license terms."); say("Please see http://forge.mysql.com/wiki/Category:RandomQueryGenerator for more information on this test framework."); say("Starting \n# $0 \\ \n# ".join(" \\ \n# ", @ARGV_saved)); # # Calculate master and slave ports based on MTR_BUILD_THREAD (MTR # Version 1 behaviour) # if (not defined $build_thread) { if (defined $ENV{MTR_BUILD_THREAD}) { $build_thread = $ENV{MTR_BUILD_THREAD} } else { $build_thread = DEFAULT_MTR_BUILD_THREAD; } } if ( $build_thread eq 'auto' ) { say ("Please set the environment variable MTR_BUILD_THREAD to a value <> 'auto' (recommended) or unset it (will take the value ".DEFAULT_MTR_BUILD_THREAD.") "); exit (STATUS_ENVIRONMENT_FAILURE); } my @ports = (10000 + 10 * $build_thread, 10000 + 10 * $build_thread + 2); say("master_port : $ports[0] slave_port : $ports[1] ports : @ports MTR_BUILD_THREAD : $build_thread "); # # If the user has provided two vardirs and one basedir, start second # server using the same basedir # if ( ($vardirs[1] ne '') && ($basedirs[1] eq '') ) { $basedirs[1] = $basedirs[0]; } if ( ($mysqld_options[1] ne '') && ($basedirs[1] eq '') ) { $basedirs[1] = $basedirs[0]; } # # If the user has provided identical basedirs and vardirs, warn of a # potential overlap. # if ( ($basedirs[0] eq $basedirs[1]) && ($vardirs[0] eq $vardirs[1]) && ($rpl_mode eq '') ) { croak("Please specify either different --basedir[12] or different --vardir[12] in order to start two MySQL servers"); } my $client_basedir; foreach my $path ("$basedirs[0]/client/RelWithDebInfo", "$basedirs[0]/client/Debug", "$basedirs[0]/client", "$basedirs[0]/bin") { if (-e $path) { $client_basedir = $path; last; } } # # Start servers. Use rpl_alter if replication is needed. # my @server; my $rplsrv; if ($rpl_mode ne '') { my @options; push @options, lc("--$engine") if defined $engine && lc($engine) ne lc('myisam'); push @options, "--sql-mode=no_engine_substitution" if join(' ', @ARGV_saved) !~ m{sql-mode}io; if (defined $mysqld_options[0]) { push @options, @{$mysqld_options[0]}; } $rplsrv = DBServer::MySQL::ReplMySQLd->new(basedir => $basedirs[0], master_vardir => $vardirs[0], master_port => $ports[0], slave_vardir => $vardirs[1], slave_port => $ports[1], mode => $rpl_mode, server_options => \@options, valgrind => $valgrind, valgrind_options => \@valgrind_options, start_dirty => $start_dirty); my $status = $rplsrv->startServer(); if ($status > DBSTATUS_OK) { stopServers(); if (osWindows()) { say(system("dir ".unix2winPath($rplsrv->master->datadir))); say(system("dir ".unix2winPath($rplsrv->slave->datadir))); } else { say(system("ls -l ".$rplsrv->master->datadir)); say(system("ls -l ".$rplsrv->slave->datadir)); } croak("Could not start replicating server pair"); } $dsns[0] = $rplsrv->master->dsn($database); $dsns[1] = undef; ## passed to gentest. No dsn for slave! $server[0] = $rplsrv->master; $server[1] = $rplsrv->slave; } else { if ($#basedirs != $#vardirs) { croak ("The number of basedirs and vardirs must match $#basedirs != $#vardirs") } foreach my $server_id (0..1) { next if $basedirs[$server_id] eq ''; my @options; push @options, lc("--$engine") if defined $engine && lc($engine) ne lc('myisam'); push @options, "--sql-mode=no_engine_substitution" if join(' ', @ARGV_saved) !~ m{sql-mode}io; if (defined $mysqld_options[$server_id]) { push @options, @{$mysqld_options[$server_id]}; } $server[$server_id] = DBServer::MySQL::MySQLd->new(basedir => $basedirs[$server_id], vardir => $vardirs[$server_id], port => $ports[$server_id], start_dirty => $start_dirty, valgrind => $valgrind, valgrind_options => \@valgrind_options, server_options => \@options); my $status = $server[$server_id]->startServer; if ($status > DBSTATUS_OK) { stopServers(); if (osWindows()) { say(system("dir ".unix2winPath($server[$server_id]->datadir))); } else { say(system("ls -l ".$server[$server_id]->datadir)); } croak("Could not start all servers"); } if ( ($server_id == 0) || ($rpl_mode eq '') ) { $dsns[$server_id] = $server[$server_id]->dsn($database); } if ((defined $dsns[$server_id]) && (defined $engine)) { my $dbh = DBI->connect($dsns[$server_id], undef, undef, { RaiseError => 1 } ); $dbh->do("SET GLOBAL storage_engine = '$engine'"); } } } # # Run actual queries # my $gentestProps = GenTest::Properties->new( legal => ['grammar', 'dsn', 'engine', 'gendata', 'generator', 'redefine', 'threads', 'queries', 'duration', 'help', 'debug', 'rpl_mode', 'validators', 'reporters', 'reporters', 'transformers', 'seed', 'mask', 'mask-level', 'rows', 'varchar-length', 'xml-output', 'views', 'start-dirty', 'filter', 'notnull', 'valgrind', 'valgrind-xml', 'testname', 'sqltrace', 'querytimeout', 'report-xml-tt', 'report-xml-tt-type', 'report-xml-tt-dest'] ); my @gentest_options; ## For backward compatability if ($#validators == 0 and $validators[0] =~ m/,/) { @validators = split(/,/,$validators[0]); } ## For backward compatability if ($#reporters == 0 and $reporters[0] =~ m/,/) { @reporters = split(/,/,$reporters[0]); } ## For backward compatability if ($#transformers == 0 and $transformers[0] =~ m/,/) { @transformers = split(/,/,$transformers[0]); } $gentestProps->property('generator','FromGrammar') if not defined $gentestProps->property('generator'); $gentestProps->property('start-dirty',1) if defined $start_dirty; $gentestProps->gendata($gendata); $gentestProps->engine($engine) if defined $engine; $gentestProps->rpl_mode($rpl_mode) if defined $rpl_mode; $gentestProps->validators(\@validators) if defined @validators; $gentestProps->reporters(\@reporters) if defined @reporters; $gentestProps->transformers(\@transformers) if defined @transformers; $gentestProps->threads($threads) if defined $threads; $gentestProps->queries($queries) if defined $queries; $gentestProps->duration($duration) if defined $duration; $gentestProps->dsn(\@dsns) if defined @dsns; $gentestProps->grammar($grammar_file); $gentestProps->redefine($redefine_file) if defined $redefine_file; $gentestProps->seed($seed) if defined $seed; $gentestProps->mask($mask) if defined $mask; $gentestProps->property('mask-level',$mask_level) if defined $mask_level; $gentestProps->rows($rows) if defined $rows; $gentestProps->views(1) if defined $views; $gentestProps->property('varchar-length',$varchar_len) if defined $varchar_len; $gentestProps->property('xml-output',$xml_output) if defined $xml_output; $gentestProps->debug(1) if defined $debug; $gentestProps->filter($filter) if defined $filter; $gentestProps->notnull($notnull) if defined $notnull; $gentestProps->valgrind(1) if $valgrind; $gentestProps->sqltrace(1) if $sqltrace; $gentestProps->querytimeout($querytimeout) if defined $querytimeout; $gentestProps->testname($testname) if $testname; $gentestProps->property('report-xml-tt', 1) if defined $report_xml_tt; $gentestProps->property('report-xml-tt-type', $report_xml_tt_type) if defined $report_xml_tt_type; $gentestProps->property('report-xml-tt-dest', $report_xml_tt_dest) if defined $report_xml_tt_dest; # Push the number of "worker" threads into the environment. # lib/GenTest/Generator/FromGrammar.pm will generate a corresponding grammar element. $ENV{RQG_THREADS}= $threads; my $gentest = GenTest::App::GenTest->new(config => $gentestProps); my $gentest_result = $gentest->run(); say("GenTest exited with exit status ".status2text($gentest_result)." ($gentest_result)"); exit_test($gentest_result) if $gentest_result > 0; # # Compare master and slave, or two masters # if ($rpl_mode || (defined $basedirs[1])) { if ($rpl_mode ne '') { $rplsrv->waitForSlaveSync; } my @dump_files; foreach my $i (0..$#server) { $dump_files[$i] = tmpdir()."server_".$$."_".$i.".dump"; my $dump_result = $server[$i]->dumpdb($database,$dump_files[$i]); exit_test($dump_result >> 8) if $dump_result > 0; } say("Comparing SQL dumps..."); my $diff_result = system("diff -u $dump_files[0] $dump_files[1]"); $diff_result = $diff_result >> 8; if ($diff_result == 0) { say("No differences were found between servers."); } foreach my $dump_file (@dump_files) { unlink($dump_file); } exit_test($diff_result); } stopServers(); sub stopServers { if ($rpl_mode ne '') { $rplsrv->stopServer(); } else { foreach my $srv (@server) { if ($srv) { $srv->stopServer; } } } } sub help { print <