PAGI-Server
view release on metacpan or search on metacpan
t/25-runner-production.t view on Meta::CPAN
subtest 'PID file creation and cleanup' => sub {
my ($fh, $pid_file) = tempfile(UNLINK => 1);
close $fh;
unlink $pid_file; # Remove it so we can test creation
# Write a minimal app file so prepare_app works without PAGI-Tools
my ($app_fh, $app_file) = tempfile(SUFFIX => '.pl', UNLINK => 1);
print $app_fh "sub { }\n";
close $app_fh;
# Start server with PID file (use fork to isolate)
my $pid = fork();
die "Cannot fork: $!" unless defined $pid;
if ($pid == 0) {
# Child process
my $runner = PAGI::Server::Runner->new(
port => 0, # Random port
quiet => 1,
);
$runner->{app_spec} = $app_file; # Use file app, not default module
$runner->prepare_app; # Load app (no PAGI-Tools needed)
# Just test PID file writing, don't run server
$runner->_write_pid_file($pid_file);
# Verify we wrote our own PID
open(my $pfh, '<', $pid_file) or exit(1);
my $written_pid = <$pfh>;
chomp $written_pid;
close $pfh;
exit($written_pid == $$ ? 0 : 1);
}
# Parent - wait for child
waitpid($pid, 0);
my $exit_code = $? >> 8;
is($exit_code, 0, 'PID file creation succeeded');
ok(-f $pid_file, 'PID file exists');
# Verify content
if (-f $pid_file) {
open(my $pfh, '<', $pid_file);
my $written_pid = <$pfh>;
chomp $written_pid;
close $pfh;
ok($written_pid =~ /^\d+$/, 'PID file contains numeric PID');
is($written_pid, $pid, 'PID matches child process');
}
# Test cleanup
my $runner = PAGI::Server::Runner->new(port => 0, quiet => 1);
$runner->{_pid_file_path} = $pid_file;
$runner->_remove_pid_file;
ok(!-f $pid_file, 'PID file removed by cleanup');
};
# 'PID file with actual server process' has been relocated to the
# PAGI-Server distribution: it forks a real PAGI::Server event loop,
# making it a server integration test rather than a Runner unit test.
# Saved verbatim to /tmp/pagi-moved-subtests.pl for that relocation task.
subtest 'User/group validation' => sub {
my $runner = PAGI::Server::Runner->new(
user => 'nonexistent_user_12345',
port => 0,
quiet => 1,
);
# Should fail for non-root trying to use --user
eval { $runner->_drop_privileges };
if ($> == 0) {
# Running as root - should reject unknown user
like($@, qr/Unknown user/, 'Rejects unknown user (as root)');
# Test unknown group
my $runner2 = PAGI::Server::Runner->new(
group => 'nonexistent_group_12345',
port => 0,
quiet => 1,
);
eval { $runner2->_drop_privileges };
like($@, qr/Unknown group/, 'Rejects unknown group (as root)');
} else {
# Not root - should require root
like($@, qr/Must run as root/, 'Requires root for --user');
# Test group also requires root
my $runner3 = PAGI::Server::Runner->new(
group => 'nogroup',
port => 0,
quiet => 1,
);
eval { $runner3->_drop_privileges };
like($@, qr/Must run as root/, 'Requires root for --group');
}
};
subtest 'CLI option parsing - daemonize' => sub {
my $runner = PAGI::Server::Runner->new;
$runner->parse_options('-D');
is($runner->{daemonize}, 1, '-D short flag sets daemonize');
my $runner2 = PAGI::Server::Runner->new;
$runner2->parse_options('--daemonize');
is($runner2->{daemonize}, 1, '--daemonize long flag sets daemonize');
};
subtest 'CLI option parsing - pid file' => sub {
my $runner = PAGI::Server::Runner->new;
$runner->parse_options('--pid', '/tmp/test.pid');
is($runner->{pid_file}, '/tmp/test.pid', '--pid option parsed');
};
subtest 'CLI option parsing - user and group' => sub {
my $runner = PAGI::Server::Runner->new;
$runner->parse_options(
'--user', 'nobody',
( run in 0.387 second using v1.01-cache-2.11-cpan-84de2e75c66 )