Changed runproduct to use an OO interface, allowing multiple copies to be run

git-svn-id: http://repo.ham.fi/svn/aprsc/trunk@228 3ce903b1-3385-4e86-93cd-f9a4a239f7ac
This commit is contained in:
Heikki Hannikainen 2008-03-22 17:30:29 +00:00
parent 40a8a9e162
commit 7c66279474
2 changed files with 88 additions and 52 deletions

View File

@ -26,57 +26,58 @@ my %products = (
'binary' => '/usr/bin/java', 'binary' => '/usr/bin/java',
'stdargs' => '-server -cp ../../../javaprssrvr/javAPRSSrvr.jar javAPRSSrvr', 'stdargs' => '-server -cp ../../../javaprssrvr/javAPRSSrvr.jar javAPRSSrvr',
'cfgfileargs' => '', 'cfgfileargs' => '',
'cfgdir' => 'cfg-javap' 'cfgdir' => 'cfg-javap',
'dieswith' => 15
} }
); );
my $prod; sub new($$)
my $prod_name = 'aprsc';
my $pid;
my($stdin, $stdout, $stderr);
sub init()
{ {
$prod_name = $ENV{'TEST_PRODUCT'} if (defined $ENV{'TEST_PRODUCT'}); my($class, $config) = @_;
my $self = bless { @_ }, $class;
if (!defined $products{$prod_name}) { if (defined $ENV{'TEST_PRODUCT'}) {
warn "No such product: " . $prod_name . "\n"; $self->{'prod_name'} = $ENV{'TEST_PRODUCT'};
} else {
$self->{'prod_name'} = 'aprsc';
}
if (!defined $products{$self->{'prod_name'}}) {
warn "No such product: " . $self->{'prod_name'} . "\n";
return undef; return undef;
} }
$prod = $products{$prod_name}; my $prod = $self->{'prod'} = $products{$self->{'prod_name'}};
return 1; my $cfgfile = $self->{'cfgfile'} = $prod->{'cfgdir'} . '/' . $config;
if (! -f $cfgfile) {
warn "No such configuration file: $cfgfile";
return undef;
}
$self->{'cmdline'} = $prod->{'binary'} . ' ' . $prod->{'stdargs'} . ' '
. $prod->{'cfgfileargs'} . ' ' . $cfgfile;
return $self;
} }
sub readout() sub readout($)
{ {
if (defined $stderr) { my($self) = @_;
}
if (defined $stdout) {
}
} }
sub start($) sub start($)
{ {
my($config) = @_; my($self) = @_;
if (defined $pid) { if (defined $self->{'pid'}) {
return "Product already running."; return "Product already running.";
} }
my $cfgfile = $prod->{'cfgdir'} . '/' . $config; warn "Product command line: $self->{cmdline}\n";
if (! -f $cfgfile) {
return "No such configuration file: $cfgfile";
}
my $cmdline = $prod->{'binary'} . ' ' . $prod->{'stdargs'} . ' ' my($stdin, $stdout, $stderr);
. $prod->{'cfgfileargs'} . ' ' . $cfgfile; my $pid = open3($stdin, $stdout, $stderr, $self->{'cmdline'});
warn "Product command line: $cmdline\n";
$pid = open3($stdin, $stdout, $stderr, $cmdline);
if (!defined $pid) { if (!defined $pid) {
return "Failed to run product: $!"; return "Failed to run product: $!";
@ -92,57 +93,86 @@ sub start($)
my $signal = $retval & 127; my $signal = $retval & 127;
$retval = $retval >> 8; $retval = $retval >> 8;
readout(); $self->readout();
discard(); $self->discard();
return "Product quit after startup, signal $signal retcode $retval."; return "Product quit after startup, signal $signal retcode $retval.";
} }
$self->{'pid'} = $pid;
$self->{'stdin'} = $stdin;
$self->{'stdout'} = $stdout;
$self->{'stderr'} = $stderr;
return 1; return 1;
} }
sub discard() sub discard($)
{ {
close($stdin) if (defined $stdin); my($self) = @_;
close($stdout) if (defined $stdout);
close($stderr) if (defined $stderr); close($self->{'stdin'}) if (defined $self->{'stdin'});
undef $pid; close($self->{'stdout'}) if (defined $self->{'stdout'});
close($self->{'stderr'}) if (defined $self->{'stderr'});
undef $self->{'stdin'};
undef $self->{'stdout'};
undef $self->{'stderr'};
undef $self->{'pid'};
} }
sub stop() sub check($)
{ {
if (!defined $pid) { my($self) = @_;
if (!defined $self->{'pid'}) {
return "Product not running."; return "Product not running.";
} }
my $kid = waitpid($pid, WNOHANG); my $kid = waitpid($self->{'pid'}, WNOHANG);
if ($kid) { if ($kid) {
my $retval = $?; my $retval = $?;
my $signal = $retval & 127; my $signal = $retval & 127;
$retval = $retval >> 8; $retval = $retval >> 8;
readout(); $self->readout();
discard(); $self->discard();
return "Product has crashed, signal $signal retcode $retval."; return "Product has crashed, signal $signal retcode $retval.";
} }
return 1;
}
sub stop($)
{
my($self) = @_;
my $ret = $self->check();
return $ret if ($ret ne 1);
my $pid = $self->{'pid'};
my $hits = kill("TERM", $pid); my $hits = kill("TERM", $pid);
if ($hits < 1) { if ($hits < 1) {
return "Product is not running."; return "Product is not running.";
discard(); $self->discard();
return undef; return undef;
} }
my $sleeptime = 0.2; my $sleeptime = 0.2;
my $maxwait = 5; my $maxwait = 6;
my $slept = 0; my $slept = 0;
my $rekilled = 0; my $rekilled = 0;
my $kid;
while (!($kid = waitpid($pid, WNOHANG))) { while (!($kid = waitpid($pid, WNOHANG))) {
$slept += select(undef, undef, undef, $sleeptime); select(undef, undef, undef, $sleeptime);
$slept += $sleeptime;
if ($slept >= $maxwait) { if ($slept >= $maxwait) {
if ($rekilled) { if ($rekilled) {
return "Product refuses to die!"; return "Product refuses to die!";
} else { } else {
warn "Sending SIGKILL...\n";
$slept = 0; $slept = 0;
$rekilled = 1; $rekilled = 1;
kill("KILL", $pid); kill("KILL", $pid);
@ -155,14 +185,18 @@ sub stop()
my $signal = $retval & 127; my $signal = $retval & 127;
$retval = $retval >> 8; $retval = $retval >> 8;
readout(); $self->readout();
discard(); $self->discard();
if ($retval ne 0 || $signal ne 0) { if ($retval ne 0 || $signal ne 0) {
return "Product has been terminated, signal $signal retcode $retval."; if (defined $self->{'prod'}->{'dieswith'} && $self->{'prod'}->{'dieswith'} eq $signal) {
# fine
} else {
return "Product has been terminated, signal $signal retcode $retval.";
}
} }
} }
discard(); $self->discard();
return 1; return 1;
} }

View File

@ -6,7 +6,9 @@ BEGIN { plan tests => 4 };
use runproduct; use runproduct;
ok(1); # If we made it this far, we're ok. ok(1); # If we made it this far, we're ok.
ok(runproduct::init(), 1, "Failed to initialize product runner"); my $p = new runproduct('basic');
ok(runproduct::start("basic"), 1, "Failed to start product");
ok(runproduct::stop(), 1, "Failed to stop product"); ok(defined $p, 1, "Failed to initialize product runner");
ok($p->start(), 1, "Failed to start product");
ok($p->stop(), 1, "Failed to stop product");