mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-30836 run_test_server() refactored
run_test_server() is actually manager main loop. We move out this function into Manager package and split into run() and parse_protocol(). The latter is needed for the fix. Moving into separate package helps to make some common variables which was local to run_test_server(). Functions from the main package is now prefixed with main:: (should be reorganized somehow later or auto-imported).
This commit is contained in:
committed by
Daniel Black
parent
92fb31f0b1
commit
0815a3b6b5
@ -483,7 +483,7 @@ sub main {
|
|||||||
mark_time_used('init');
|
mark_time_used('init');
|
||||||
|
|
||||||
my ($prefix, $fail, $completed, $extra_warnings)=
|
my ($prefix, $fail, $completed, $extra_warnings)=
|
||||||
run_test_server($server, $tests, \%children);
|
Manager::run($server, $tests, \%children);
|
||||||
|
|
||||||
exit(0) if $opt_start_exit;
|
exit(0) if $opt_start_exit;
|
||||||
|
|
||||||
@ -562,24 +562,205 @@ sub main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub run_test_server ($$$) {
|
package Manager;
|
||||||
|
use POSIX ":sys_wait_h";
|
||||||
|
use File::Basename;
|
||||||
|
use File::Find;
|
||||||
|
use IO::Socket::INET;
|
||||||
|
use IO::Select;
|
||||||
|
use mtr_report;
|
||||||
|
use My::Platform;
|
||||||
|
|
||||||
|
my $num_saved_datadir; # Number of datadirs saved in vardir/log/ so far.
|
||||||
|
my $num_failed_test; # Number of tests failed so far
|
||||||
|
my $test_failure; # Set true if test suite failed
|
||||||
|
my $extra_warnings; # Warnings found during server shutdowns
|
||||||
|
|
||||||
|
my $completed;
|
||||||
|
my %running;
|
||||||
|
my $result;
|
||||||
|
my $exe_mysqld; # Used as hint to CoreDump
|
||||||
|
my %names;
|
||||||
|
|
||||||
|
sub parse_protocol($$) {
|
||||||
|
my $sock= shift;
|
||||||
|
my $line= shift;
|
||||||
|
|
||||||
|
if ($line eq 'TESTRESULT'){
|
||||||
|
mtr_verbose2("Got TESTRESULT from ". $names{$sock});
|
||||||
|
$result= My::Test::read_test($sock);
|
||||||
|
|
||||||
|
# Report test status
|
||||||
|
mtr_report_test($result);
|
||||||
|
|
||||||
|
if ( $result->is_failed() ) {
|
||||||
|
|
||||||
|
# Save the workers "savedir" in var/log
|
||||||
|
my $worker_savedir= $result->{savedir};
|
||||||
|
my $worker_savename= basename($worker_savedir);
|
||||||
|
my $savedir= "$opt_vardir/log/$worker_savename";
|
||||||
|
|
||||||
|
# Move any core files from e.g. mysqltest
|
||||||
|
foreach my $coref (glob("core*"), glob("*.dmp"))
|
||||||
|
{
|
||||||
|
mtr_report(" - found '$coref', moving it to '$worker_savedir'");
|
||||||
|
move($coref, $worker_savedir);
|
||||||
|
}
|
||||||
|
|
||||||
|
find(
|
||||||
|
{
|
||||||
|
no_chdir => 1,
|
||||||
|
wanted => sub
|
||||||
|
{
|
||||||
|
My::CoreDump::core_wanted(\$num_saved_cores,
|
||||||
|
$opt_max_save_core,
|
||||||
|
@opt_cases == 0,
|
||||||
|
$exe_mysqld, $opt_parallel);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$worker_savedir);
|
||||||
|
|
||||||
|
if ($num_saved_datadir >= $opt_max_save_datadir)
|
||||||
|
{
|
||||||
|
mtr_report(" - skipping '$worker_savedir/'");
|
||||||
|
main::rmtree($worker_savedir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtr_report(" - saving '$worker_savedir/' to '$savedir/'");
|
||||||
|
rename($worker_savedir, $savedir);
|
||||||
|
$num_saved_datadir++;
|
||||||
|
}
|
||||||
|
main::resfile_print_test();
|
||||||
|
$num_failed_test++ unless ($result->{retries} ||
|
||||||
|
$result->{exp_fail});
|
||||||
|
|
||||||
|
$test_failure= 1;
|
||||||
|
if ( !$opt_force ) {
|
||||||
|
# Test has failed, force is off
|
||||||
|
push(@$completed, $result);
|
||||||
|
if ($result->{'dont_kill_server'})
|
||||||
|
{
|
||||||
|
mtr_verbose2("${line}: saying BYE to ". $names{$sock});
|
||||||
|
print $sock "BYE\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return ["Failure", 1, $completed, $extra_warnings];
|
||||||
|
}
|
||||||
|
elsif ($opt_max_test_fail > 0 and
|
||||||
|
$num_failed_test >= $opt_max_test_fail) {
|
||||||
|
push(@$completed, $result);
|
||||||
|
mtr_report("Too many tests($num_failed_test) failed!",
|
||||||
|
"Terminating...");
|
||||||
|
return ["Too many failed", 1, $completed, $extra_warnings];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main::resfile_print_test();
|
||||||
|
# Retry test run after test failure
|
||||||
|
my $retries= $result->{retries} || 2;
|
||||||
|
my $test_has_failed= $result->{failures} || 0;
|
||||||
|
if ($test_has_failed and $retries <= $opt_retry){
|
||||||
|
# Test should be run one more time unless it has failed
|
||||||
|
# too many times already
|
||||||
|
my $tname= $result->{name};
|
||||||
|
my $failures= $result->{failures};
|
||||||
|
if ($opt_retry > 1 and $failures >= $opt_retry_failure){
|
||||||
|
mtr_report("\nTest $tname has failed $failures times,",
|
||||||
|
"no more retries!\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mtr_report("\nRetrying test $tname, ".
|
||||||
|
"attempt($retries/$opt_retry)...\n");
|
||||||
|
#saving the log file as filename.failed in case of retry
|
||||||
|
if ( $result->is_failed() ) {
|
||||||
|
my $worker_logdir= $result->{savedir};
|
||||||
|
my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log";
|
||||||
|
|
||||||
|
if (-e $log_file_name) {
|
||||||
|
$result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20);
|
||||||
|
} else {
|
||||||
|
$result->{'logfile-failed'} = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
rename $log_file_name, $log_file_name.".failed";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
local @$result{'retries', 'result'};
|
||||||
|
delete $result->{result};
|
||||||
|
$result->{retries}= $retries+1;
|
||||||
|
$result->write_test($sock, 'TESTCASE');
|
||||||
|
}
|
||||||
|
push(@$completed, $result);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Repeat test $opt_repeat number of times
|
||||||
|
my $repeat= $result->{repeat} || 1;
|
||||||
|
if ($repeat < $opt_repeat)
|
||||||
|
{
|
||||||
|
$result->{retries}= 0;
|
||||||
|
$result->{rep_failures}++ if $result->{failures};
|
||||||
|
$result->{failures}= 0;
|
||||||
|
delete($result->{result});
|
||||||
|
$result->{repeat}= $repeat+1;
|
||||||
|
$result->write_test($sock, 'TESTCASE');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove from list of running
|
||||||
|
mtr_error("'", $result->{name},"' is not known to be running")
|
||||||
|
unless delete $running{$result->key()};
|
||||||
|
|
||||||
|
# Save result in completed list
|
||||||
|
push(@$completed, $result);
|
||||||
|
|
||||||
|
} # if ($line eq 'TESTRESULT')
|
||||||
|
elsif ($line=~ /^START (.*)$/){
|
||||||
|
# Send first test
|
||||||
|
$names{$sock}= $1;
|
||||||
|
}
|
||||||
|
elsif ($line eq 'WARNINGS'){
|
||||||
|
my $fake_test= My::Test::read_test($sock);
|
||||||
|
my $test_list= join (" ", @{$fake_test->{testnames}});
|
||||||
|
push @$extra_warnings, $test_list;
|
||||||
|
my $report= $fake_test->{'warnings'};
|
||||||
|
mtr_report("***Warnings generated in error logs during shutdown ".
|
||||||
|
"after running tests: $test_list\n\n$report");
|
||||||
|
$test_failure= 1;
|
||||||
|
if ( !$opt_force ) {
|
||||||
|
# Test failure due to warnings, force is off
|
||||||
|
mtr_verbose2("Socket loop exiting 3");
|
||||||
|
return ["Warnings in log", 1, $completed, $extra_warnings];
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
elsif ($line =~ /^SPENT/) {
|
||||||
|
main::add_total_times($line);
|
||||||
|
}
|
||||||
|
elsif ($line eq 'VALGREP' && $opt_valgrind) {
|
||||||
|
$valgrind_reports= 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mtr_error("Unknown response: '$line' from client");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub run ($$$) {
|
||||||
my ($server, $tests, $children) = @_;
|
my ($server, $tests, $children) = @_;
|
||||||
|
my $suite_timeout= main::start_timer(main::suite_timeout());
|
||||||
my $num_saved_datadir= 0; # Number of datadirs saved in vardir/log/ so far.
|
$exe_mysqld= main::find_mysqld($bindir) || ""; # Used as hint to CoreDump
|
||||||
my $num_failed_test= 0; # Number of tests failed so far
|
$num_saved_datadir= 0; # Number of datadirs saved in vardir/log/ so far.
|
||||||
my $test_failure= 0; # Set true if test suite failed
|
$num_failed_test= 0; # Number of tests failed so far
|
||||||
my $extra_warnings= []; # Warnings found during server shutdowns
|
$test_failure= 0; # Set true if test suite failed
|
||||||
|
$extra_warnings= []; # Warnings found during server shutdowns
|
||||||
my $completed= [];
|
$completed= [];
|
||||||
my %running;
|
|
||||||
my $result;
|
|
||||||
my $exe_mysqld= find_mysqld($bindir) || ""; # Used as hint to CoreDump
|
|
||||||
|
|
||||||
my $suite_timeout= start_timer(suite_timeout());
|
|
||||||
|
|
||||||
my $s= IO::Select->new();
|
my $s= IO::Select->new();
|
||||||
my $childs= 0;
|
my $childs= 0;
|
||||||
my %names;
|
|
||||||
$s->add($server);
|
$s->add($server);
|
||||||
while (1) {
|
while (1) {
|
||||||
if ($opt_stop_file)
|
if ($opt_stop_file)
|
||||||
@ -587,16 +768,16 @@ sub run_test_server ($$$) {
|
|||||||
if (mtr_wait_lock_file($opt_stop_file, $opt_stop_keep_alive))
|
if (mtr_wait_lock_file($opt_stop_file, $opt_stop_keep_alive))
|
||||||
{
|
{
|
||||||
# We were waiting so restart timer process
|
# We were waiting so restart timer process
|
||||||
my $suite_timeout= start_timer(suite_timeout());
|
my $suite_timeout= main::start_timer(main::suite_timeout());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_time_used('admin');
|
main::mark_time_used('admin');
|
||||||
my @ready = $s->can_read(1); # Wake up once every second
|
my @ready = $s->can_read(1); # Wake up once every second
|
||||||
if (@ready > 0) {
|
if (@ready > 0) {
|
||||||
mtr_verbose2("Got ". (0 + @ready). " connection(s)");
|
mtr_verbose2("Got ". (0 + @ready). " connection(s)");
|
||||||
}
|
}
|
||||||
mark_time_idle();
|
main::mark_time_idle();
|
||||||
my $i= 0;
|
my $i= 0;
|
||||||
foreach my $sock (@ready) {
|
foreach my $sock (@ready) {
|
||||||
++$i;
|
++$i;
|
||||||
@ -619,163 +800,14 @@ sub run_test_server ($$$) {
|
|||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
chomp($line);
|
chomp($line);
|
||||||
|
mtr_verbose2("Connection ${i}". (exists $names{$sock} ? " from $names{$sock}" : "") .": $line");
|
||||||
|
|
||||||
if ($line eq 'TESTRESULT'){
|
my $res= parse_protocol($sock, $line);
|
||||||
$result= My::Test::read_test($sock);
|
if (ref $res eq 'ARRAY') {
|
||||||
|
return @$res;
|
||||||
# Report test status
|
} elsif ($res == 1) {
|
||||||
mtr_report_test($result);
|
next;
|
||||||
|
|
||||||
if ( $result->is_failed() ) {
|
|
||||||
|
|
||||||
# Save the workers "savedir" in var/log
|
|
||||||
my $worker_savedir= $result->{savedir};
|
|
||||||
my $worker_savename= basename($worker_savedir);
|
|
||||||
my $savedir= "$opt_vardir/log/$worker_savename";
|
|
||||||
|
|
||||||
# Move any core files from e.g. mysqltest
|
|
||||||
foreach my $coref (glob("core*"), glob("*.dmp"))
|
|
||||||
{
|
|
||||||
mtr_report(" - found '$coref', moving it to '$worker_savedir'");
|
|
||||||
move($coref, $worker_savedir);
|
|
||||||
}
|
|
||||||
|
|
||||||
find(
|
|
||||||
{
|
|
||||||
no_chdir => 1,
|
|
||||||
wanted => sub
|
|
||||||
{
|
|
||||||
My::CoreDump::core_wanted(\$num_saved_cores,
|
|
||||||
$opt_max_save_core,
|
|
||||||
@opt_cases == 0,
|
|
||||||
$exe_mysqld, $opt_parallel);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
$worker_savedir);
|
|
||||||
|
|
||||||
if ($num_saved_datadir >= $opt_max_save_datadir)
|
|
||||||
{
|
|
||||||
mtr_report(" - skipping '$worker_savedir/'");
|
|
||||||
rmtree($worker_savedir);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtr_report(" - saving '$worker_savedir/' to '$savedir/'");
|
|
||||||
rename($worker_savedir, $savedir);
|
|
||||||
$num_saved_datadir++;
|
|
||||||
}
|
|
||||||
resfile_print_test();
|
|
||||||
$num_failed_test++ unless ($result->{retries} ||
|
|
||||||
$result->{exp_fail});
|
|
||||||
|
|
||||||
$test_failure= 1;
|
|
||||||
if ( !$opt_force ) {
|
|
||||||
# Test has failed, force is off
|
|
||||||
push(@$completed, $result);
|
|
||||||
if ($result->{'dont_kill_server'})
|
|
||||||
{
|
|
||||||
print $sock "BYE\n";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
return ("Failure", 1, $completed, $extra_warnings);
|
|
||||||
}
|
|
||||||
elsif ($opt_max_test_fail > 0 and
|
|
||||||
$num_failed_test >= $opt_max_test_fail) {
|
|
||||||
push(@$completed, $result);
|
|
||||||
mtr_report("Too many tests($num_failed_test) failed!",
|
|
||||||
"Terminating...");
|
|
||||||
return ("Too many failed", 1, $completed, $extra_warnings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resfile_print_test();
|
|
||||||
# Retry test run after test failure
|
|
||||||
my $retries= $result->{retries} || 2;
|
|
||||||
my $test_has_failed= $result->{failures} || 0;
|
|
||||||
if ($test_has_failed and $retries <= $opt_retry){
|
|
||||||
# Test should be run one more time unless it has failed
|
|
||||||
# too many times already
|
|
||||||
my $tname= $result->{name};
|
|
||||||
my $failures= $result->{failures};
|
|
||||||
if ($opt_retry > 1 and $failures >= $opt_retry_failure){
|
|
||||||
mtr_report("\nTest $tname has failed $failures times,",
|
|
||||||
"no more retries!\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mtr_report("\nRetrying test $tname, ".
|
|
||||||
"attempt($retries/$opt_retry)...\n");
|
|
||||||
#saving the log file as filename.failed in case of retry
|
|
||||||
if ( $result->is_failed() ) {
|
|
||||||
my $worker_logdir= $result->{savedir};
|
|
||||||
my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log";
|
|
||||||
|
|
||||||
if (-e $log_file_name) {
|
|
||||||
$result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20);
|
|
||||||
} else {
|
|
||||||
$result->{'logfile-failed'} = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
rename $log_file_name, $log_file_name.".failed";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
local @$result{'retries', 'result'};
|
|
||||||
delete $result->{result};
|
|
||||||
$result->{retries}= $retries+1;
|
|
||||||
$result->write_test($sock, 'TESTCASE');
|
|
||||||
}
|
|
||||||
push(@$completed, $result);
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Repeat test $opt_repeat number of times
|
|
||||||
my $repeat= $result->{repeat} || 1;
|
|
||||||
if ($repeat < $opt_repeat)
|
|
||||||
{
|
|
||||||
$result->{retries}= 0;
|
|
||||||
$result->{rep_failures}++ if $result->{failures};
|
|
||||||
$result->{failures}= 0;
|
|
||||||
delete($result->{result});
|
|
||||||
$result->{repeat}= $repeat+1;
|
|
||||||
$result->write_test($sock, 'TESTCASE');
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove from list of running
|
|
||||||
mtr_error("'", $result->{name},"' is not known to be running")
|
|
||||||
unless delete $running{$result->key()};
|
|
||||||
|
|
||||||
# Save result in completed list
|
|
||||||
push(@$completed, $result);
|
|
||||||
|
|
||||||
}
|
|
||||||
elsif ($line=~ /^START (.*)$/){
|
|
||||||
# Send first test
|
|
||||||
$names{$sock}= $1;
|
|
||||||
}
|
|
||||||
elsif ($line eq 'WARNINGS'){
|
|
||||||
my $fake_test= My::Test::read_test($sock);
|
|
||||||
my $test_list= join (" ", @{$fake_test->{testnames}});
|
|
||||||
push @$extra_warnings, $test_list;
|
|
||||||
my $report= $fake_test->{'warnings'};
|
|
||||||
mtr_report("***Warnings generated in error logs during shutdown ".
|
|
||||||
"after running tests: $test_list\n\n$report");
|
|
||||||
$test_failure= 1;
|
|
||||||
if ( !$opt_force ) {
|
|
||||||
# Test failure due to warnings, force is off
|
|
||||||
return ("Warnings in log", 1, $completed, $extra_warnings);
|
|
||||||
}
|
|
||||||
next;
|
|
||||||
}
|
}
|
||||||
elsif ($line =~ /^SPENT/) {
|
|
||||||
add_total_times($line);
|
|
||||||
}
|
|
||||||
elsif ($line eq 'VALGREP' && $opt_valgrind) {
|
|
||||||
$valgrind_reports= 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mtr_error("Unknown response: '$line' from client");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find next test to schedule
|
# Find next test to schedule
|
||||||
# - Try to use same configuration as worker used last time
|
# - Try to use same configuration as worker used last time
|
||||||
@ -788,7 +820,7 @@ sub run_test_server ($$$) {
|
|||||||
|
|
||||||
last unless defined $t;
|
last unless defined $t;
|
||||||
|
|
||||||
if (run_testcase_check_skip_test($t)){
|
if (main::run_testcase_check_skip_test($t)){
|
||||||
# Move the test to completed list
|
# Move the test to completed list
|
||||||
#mtr_report("skip - Moving test $i to completed");
|
#mtr_report("skip - Moving test $i to completed");
|
||||||
push(@$completed, splice(@$tests, $i, 1));
|
push(@$completed, splice(@$tests, $i, 1));
|
||||||
@ -889,7 +921,7 @@ sub run_test_server ($$$) {
|
|||||||
# ----------------------------------------------------
|
# ----------------------------------------------------
|
||||||
# Check if test suite timer expired
|
# Check if test suite timer expired
|
||||||
# ----------------------------------------------------
|
# ----------------------------------------------------
|
||||||
if ( has_expired($suite_timeout) )
|
if ( main::has_expired($suite_timeout) )
|
||||||
{
|
{
|
||||||
mtr_report("Test suite timeout! Terminating...");
|
mtr_report("Test suite timeout! Terminating...");
|
||||||
return ("Timeout", 1, $completed, $extra_warnings);
|
return ("Timeout", 1, $completed, $extra_warnings);
|
||||||
@ -897,6 +929,9 @@ sub run_test_server ($$$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
package main;
|
||||||
|
|
||||||
sub run_worker ($) {
|
sub run_worker ($) {
|
||||||
my ($server_port, $thread_num)= @_;
|
my ($server_port, $thread_num)= @_;
|
||||||
|
Reference in New Issue
Block a user