1
package Test::Nginx::Util;
10
use POSIX qw( SIGQUIT SIGKILL SIGTERM );
13
use Module::Install::Can;
15
use List::Util qw( shuffle );
16
use Time::HiRes qw( sleep );
18
our $NoNginxManager = 0;
22
our $MAX_PROCESSES = 10;
33
eval "use Parallel::ForkManager";
35
die "Failed to load Parallel::ForkManager: $@\n";
37
$ForkManager = new Parallel::ForkManager($MAX_PROCESSES);
41
our $WorkerConnections = 64;
42
our $LogLevel = 'debug';
43
our $MasterProcessEnabled = 'on';
44
our $DaemonEnabled = 'on';
45
our $ServerPort = 1984;
46
our $ServerPortForClient = 1984;
47
our $NoRootLocation = 1;
58
sub worker_connections (@) {
60
$WorkerConnections = shift;
62
return $WorkerConnections;
66
sub no_root_location () {
72
#warn "setting workers to $_[0]";
88
$MasterProcessEnabled = 'on';
91
sub master_process_enabled (@) {
93
$MasterProcessEnabled = shift() ? 'on' : 'off';
95
return $MasterProcessEnabled;
122
master_process_enabled
130
$DaemonEnabled = 'off';
131
$MasterProcessEnabled = 'off';
134
our $ConfigPreamble = '';
136
sub config_preamble ($) {
137
$ConfigPreamble = shift;
143
our $NginxRawVersion;
146
#our ($PrevRequest, $PrevConfig);
148
our $ServRoot = File::Spec->catfile(cwd(), 't/servroot');
149
our $LogDir = File::Spec->catfile($ServRoot, 'logs');
150
our $ErrLogFile = File::Spec->catfile($LogDir, 'error.log');
151
our $AccLogFile = File::Spec->catfile($LogDir, 'access.log');
152
our $HtmlDir = File::Spec->catfile($ServRoot, 'html');
153
our $ConfDir = File::Spec->catfile($ServRoot, 'conf');
154
our $ConfFile = File::Spec->catfile($ConfDir, 'nginx.conf');
155
our $PidFile = File::Spec->catfile($LogDir, 'nginx.pid');
158
$NginxVersion = get_nginx_version();
160
if (defined $NginxVersion) {
161
#warn "[INFO] Using nginx version $NginxVersion ($NginxRawVersion)\n";
164
for my $block ($NoShuffle ? Test::Base::blocks() : shuffle Test::Base::blocks()) {
171
$ForkManager->wait_all_children;
175
sub setup_server_root () {
178
#die ".pid file $PidFile exists.\n";
179
system("rm -rf t/servroot > /dev/null") == 0 or
180
die "Can't remove t/servroot";
184
die "Failed to do mkdir $ServRoot\n";
186
die "Failed to do mkdir $LogDir\n";
188
die "Failed to do mkdir $HtmlDir\n";
190
my $index_file = "$HtmlDir/index.html";
192
open my $out, ">$index_file" or
193
die "Can't open $index_file for writing: $!\n";
195
print $out '<html><head><title>It works!</title></head><body>It works!</body></html>';
200
die "Failed to do mkdir $ConfDir\n";
203
sub write_config_file ($$) {
204
my ($config, $http_config) = @_;
206
if (!defined $config) {
210
if (!defined $http_config) {
214
open my $out, ">$ConfFile" or
215
die "Can't open $ConfFile for writing: $!\n";
217
worker_processes $Workers;
218
daemon $DaemonEnabled;
219
master_process $MasterProcessEnabled;
220
error_log $ErrLogFile $LogLevel;
224
access_log $AccLogFile;
226
default_type text/plain;
227
keepalive_timeout 68;
235
client_max_body_size 30M;
236
#client_body_buffer_size 4k;
238
# Begin preamble config...
240
# End preamble config...
242
# Begin test case config...
244
# End test case config.
248
if (! $NoRootLocation) {
252
index index.html index.htm;
262
worker_connections $WorkerConnections;
269
sub get_canon_version (@) {
270
sprintf "%d.%03d%03d", $_[0], $_[1], $_[2];
273
sub get_nginx_version () {
274
my $out = `nginx -V 2>&1`;
275
if (!defined $out || $? != 0) {
276
warn "Failed to get the version of the Nginx in PATH.\n";
278
if ($out =~ m{nginx/(\d+)\.(\d+)\.(\d+)}s) {
279
$NginxRawVersion = "$1.$2.$3";
280
return get_canon_version($1, $2, $3);
282
warn "Failed to parse the output of \"nginx -V\": $out\n";
286
sub get_pid_from_pidfile ($) {
288
open my $in, $PidFile or
289
Test::More::BAIL_OUT("$name - Failed to open the pid file $PidFile for reading: $!");
290
my $pid = do { local $/; <$in> };
297
(my $s = shift) =~ s/^\s+|\s+$//g;
303
sub show_all_chars ($) {
311
sub parse_headers ($) {
314
open my $in, '<', \$s;
317
my ($key, $val) = split /\s*:\s*/, $_, 2;
318
$headers{$key} = $val;
326
my $name = $block->name;
328
my $config = $block->config;
329
if (!defined $config) {
330
Test::More::BAIL_OUT("$name - No '--- config' section specified");
331
#$config = $PrevConfig;
335
my $skip_nginx = $block->skip_nginx;
336
my ($tests_to_skip, $should_skip, $skip_reason);
337
if (defined $skip_nginx) {
338
if ($skip_nginx =~ m{
339
^ \s* (\d+) \s* : \s*
340
([<>]=?) \s* (\d+)\.(\d+)\.(\d+)
341
(?: \s* : \s* (.*) )?
344
my ($op, $ver1, $ver2, $ver3) = ($2, $3, $4, $5);
346
#warn "$ver1 $ver2 $ver3";
347
my $ver = get_canon_version($ver1, $ver2, $ver3);
348
if ((!defined $NginxVersion and $op =~ /^</)
349
or eval "$NginxVersion $op $ver")
354
Test::More::BAIL_OUT("$name - Invalid --- skip_nginx spec: " .
359
if (!defined $skip_reason) {
360
$skip_reason = "various reasons";
363
my $todo_nginx = $block->todo_nginx;
364
my ($should_todo, $todo_reason);
365
if (defined $todo_nginx) {
366
if ($todo_nginx =~ m{
368
([<>]=?) \s* (\d+)\.(\d+)\.(\d+)
369
(?: \s* : \s* (.*) )?
371
my ($op, $ver1, $ver2, $ver3) = ($1, $2, $3, $4);
373
my $ver = get_canon_version($ver1, $ver2, $ver3);
374
if ((!defined $NginxVersion and $op =~ /^</)
375
or eval "$NginxVersion $op $ver")
380
Test::More::BAIL_OUT("$name - Invalid --- todo_nginx spec: " .
386
if (!defined $todo_reason) {
387
$todo_reason = "various reasons";
390
if (!$NoNginxManager && !$should_skip) {
391
my $nginx_is_running = 1;
393
my $pid = get_pid_from_pidfile($name);
394
if (!defined $pid or $pid eq '') {
395
undef $nginx_is_running;
399
if (system("ps $pid > /dev/null") == 0) {
400
#warn "found running nginx...";
401
write_config_file($config, $block->http_config);
402
if (kill(SIGQUIT, $pid) == 0) { # send quit signal
403
#warn("$name - Failed to send quit signal to the nginx process with PID $pid");
406
if (system("ps $pid > /dev/null") == 0) {
407
#warn "killing with force...\n";
411
undef $nginx_is_running;
414
die "Failed to remove pid file $PidFile\n";
415
undef $nginx_is_running;
418
undef $nginx_is_running;
423
unless ($nginx_is_running) {
424
#system("killall -9 nginx");
426
#warn "*** Restarting the nginx server...\n";
428
write_config_file($config, $block->http_config);
429
if ( ! Module::Install::Can->can_run('nginx') ) {
430
Test::More::BAIL_OUT("$name - Cannot find the nginx executable in the PATH environment");
433
#if (system("nginx -p $ServRoot -c $ConfFile -t") != 0) {
434
#Test::More::BAIL_OUT("$name - Invalid config file");
436
#my $cmd = "nginx -p $ServRoot -c $ConfFile > /dev/null";
438
if ($NginxVersion >= 0.007053) {
439
$cmd = "nginx -p $ServRoot/ -c $ConfFile > /dev/null";
441
$cmd = "nginx -c $ConfFile > /dev/null";
445
my $pid = $ForkManager->start;
448
if (system($cmd) != 0) {
449
Test::More::BAIL_OUT("$name - Cannot start nginx using command \"$cmd\".");
452
$ForkManager->finish; # terminate the child process
455
if (system($cmd) != 0) {
456
Test::More::BAIL_OUT("$name - Cannot start nginx using command \"$cmd\".");
467
Test::More::BAIL_OUT("$name - init failed: $@");
472
while ($i++ < $RepeatEach) {
475
Test::More::skip("$name - $skip_reason", $tests_to_skip);
477
$RunTestHelper->($block);
479
} elsif ($should_todo) {
481
local $TODO = "$name - $todo_reason";
483
$RunTestHelper->($block);
486
$RunTestHelper->($block);
490
if (defined $block->quit && $Profiling) {
491
warn "Found quit...";
493
my $pid = get_pid_from_pidfile($name);
494
if (system("ps $pid > /dev/null") == 0) {
495
write_config_file($config, $block->http_config);
496
if (kill(SIGQUIT, $pid) == 0) { # send quit signal
497
#warn("$name - Failed to send quit signal to the nginx process with PID $pid");
500
if (system("ps $pid > /dev/null") == 0) {
501
#warn "killing with force...\n";
507
die "Failed to remove pid file $PidFile\n";