# HG changeset patch # User Maxim Dounin # Date 1221238235 -14400 # Node ID d4b74207a627df0f3f5739a74de6b1e452fce055 # Parent e8edb765595d5fdfb791ff364f93a99e461bd6fa Tests: refactor common functions. Let it be something more structured, avoid globals. diff --git a/_common.pm b/lib/Test/Nginx.pm rename from _common.pm rename to lib/Test/Nginx.pm --- a/_common.pm +++ b/lib/Test/Nginx.pm @@ -1,4 +1,4 @@ -package _common; +package Test::Nginx; # (C) Maxim Dounin @@ -11,30 +11,38 @@ use strict; use base qw/ Exporter /; -our @EXPORT = qw/ start_nginx write_file smtp_connect smtp_send smtp_read - smtp_check smtp_ok log_in log_out http /; +our @EXPORT = qw/ log_in log_out http /; ############################################################################### -use Test::More; use File::Temp qw/ tempdir /; use IO::Socket; use Socket qw/ CRLF /; -our $testdir; -our $s; +############################################################################### -############################################################################### +sub new { + my $self = {}; + bless $self; + return $self; +} + +sub DESTROY { + my ($self) = @_; + $self->stop(); +} # Create temp directory and run nginx instance. -sub start_nginx { - my ($conf) = @_; +sub run { + my ($self, $conf) = @_; - $testdir = tempdir('nginx-test-XXXXXXXXXX', TMPDIR => 1, + my $testdir = tempdir('nginx-test-XXXXXXXXXX', TMPDIR => 1, CLEANUP => not $ENV{LEAVE}) or die "Can't create temp directory: $!\n"; + $self->{_testdir} = $testdir; + system("cat $conf | sed 's!%%TESTDIR%%!$testdir!g' " . "> $testdir/nginx.conf"); @@ -51,25 +59,29 @@ sub start_nginx { # wait for nginx to start sleep 1; + + return $self; } -sub stop_nginx { +sub stop { + my ($self) = @_; + # terminate nginx by SIGTERM - kill 15, `cat $testdir/nginx.pid`; + kill 15, `cat $self->{_testdir}/nginx.pid`; wait; -} -END { - stop_nginx(); + return $self; } sub write_file { - my ($name, $content) = @_; + my ($self, $name, $content) = @_; - open F, '>' . $testdir . '/' . $name + open F, '>' . $self->{_testdir} . '/' . $name or die "Can't create $name: $!"; print F $content; close F; + + return $self; } ############################################################################### @@ -118,56 +130,6 @@ sub http { ############################################################################### -sub smtp_connect { - $s = IO::Socket::INET->new( - Proto => "tcp", - PeerAddr => "localhost", - PeerPort => 10025, - @_ - ) - or die "Can't connect to nginx: $!\n"; - - $s->autoflush(1); - - return $s; -} - -sub smtp_send { - my ($cmd) = @_; - log_out($cmd); - $s->print($cmd . CRLF); -} - -sub smtp_read { - my ($regex, $name) = @_; - eval { - alarm(2); - local $SIG{ALRM} = sub { die "alarm\n" }; - while (<$s>) { - log_in($_); - next if m/^\d\d\d-/; - last; - } - alarm(0); - }; - alarm(0); - if ($@) { - return undef; - } - return $_; -} - -sub smtp_check { - my ($regex, $name) = @_; - like(smtp_read(), $regex, $name); -} - -sub smtp_ok { - smtp_check(qr/^2\d\d /, @_); -} - -############################################################################### - 1; ############################################################################### diff --git a/_common.pm b/lib/Test/Nginx/SMTP.pm copy from _common.pm copy to lib/Test/Nginx/SMTP.pm --- a/_common.pm +++ b/lib/Test/Nginx/SMTP.pm @@ -1,125 +1,26 @@ -package _common; +package Test::Nginx::SMTP; # (C) Maxim Dounin -# Generict module for nginx tests. +# Module for nginx smtp tests. ############################################################################### use warnings; use strict; -use base qw/ Exporter /; - -our @EXPORT = qw/ start_nginx write_file smtp_connect smtp_send smtp_read - smtp_check smtp_ok log_in log_out http /; - -############################################################################### - -use Test::More; -use File::Temp qw/ tempdir /; +use Test::More qw//; use IO::Socket; use Socket qw/ CRLF /; -our $testdir; -our $s; - -############################################################################### - -# Create temp directory and run nginx instance. - -sub start_nginx { - my ($conf) = @_; - - $testdir = tempdir('nginx-test-XXXXXXXXXX', TMPDIR => 1, - CLEANUP => not $ENV{LEAVE}) - or die "Can't create temp directory: $!\n"; - - system("cat $conf | sed 's!%%TESTDIR%%!$testdir!g' " - . "> $testdir/nginx.conf"); - - my $pid = fork(); - die "Unable to fork(): $!\n" unless defined $pid; +use Test::Nginx; - if ($pid == 0) { - exec('../nginx/objs/nginx', '-c', "$testdir/nginx.conf", '-g', - "pid $testdir/nginx.pid; " - . "error_log $testdir/nginx-error.log debug;") - or die "Unable to exec(): $!\n"; - } - - # wait for nginx to start - - sleep 1; -} - -sub stop_nginx { - # terminate nginx by SIGTERM - kill 15, `cat $testdir/nginx.pid`; - wait; -} - -END { - stop_nginx(); -} - -sub write_file { - my ($name, $content) = @_; +use base qw/ IO::Socket::INET /; - open F, '>' . $testdir . '/' . $name - or die "Can't create $name: $!"; - print F $content; - close F; -} - -############################################################################### - -sub log_out { - my ($msg) = @_; - $msg =~ s/^/# >> /gm; - $msg .= "\n" unless $msg =~ /\n\Z/; - print $msg; -} - -sub log_in { - my ($msg) = @_; - $msg =~ s/^/# << /gm; - $msg =~ s/([^\x20-\x7e])/sprintf('\\x%02x', ord($1)) . (($1 eq "\n") ? "\n" : '')/gmxe; - $msg .= "\n" unless $msg =~ /\n\Z/; - print $msg; -} - -############################################################################### +sub new { + my $class = shift; -sub http { - my ($request) = @_; - my $reply; - eval { - local $SIG{ALRM} = sub { die "alarm\n" }; - alarm(2); - my $s = IO::Socket::INET->new( - Proto => 'tcp', - PeerHost => 'localhost:8080' - ); - log_out($request); - $s->print($request); - local $/; - $reply = $s->getline(); - log_in($reply); - alarm(0); - }; - alarm(0); - if ($@) { - log_in('(timeout)'); - return undef; - } - return $reply; -} - -############################################################################### - -sub smtp_connect { - $s = IO::Socket::INET->new( + my $self = return $class->SUPER::new( Proto => "tcp", PeerAddr => "localhost", PeerPort => 10025, @@ -127,23 +28,23 @@ sub smtp_connect { ) or die "Can't connect to nginx: $!\n"; - $s->autoflush(1); + $self->autoflush(1); - return $s; + return $self; } -sub smtp_send { - my ($cmd) = @_; +sub send { + my ($self, $cmd) = @_; log_out($cmd); - $s->print($cmd . CRLF); + $self->print($cmd . CRLF); } -sub smtp_read { - my ($regex, $name) = @_; +sub read { + my ($self) = @_; eval { alarm(2); local $SIG{ALRM} = sub { die "alarm\n" }; - while (<$s>) { + while (<$self>) { log_in($_); next if m/^\d\d\d-/; last; @@ -157,13 +58,14 @@ sub smtp_read { return $_; } -sub smtp_check { - my ($regex, $name) = @_; - like(smtp_read(), $regex, $name); +sub check { + my ($self, $regex, $name) = @_; + Test::More::like($self->read(), $regex, $name); } -sub smtp_ok { - smtp_check(qr/^2\d\d /, @_); +sub ok { + my $self = shift; + $self->check(qr/^2\d\d /, @_); } ############################################################################### diff --git a/smtp.t b/smtp.t --- a/smtp.t +++ b/smtp.t @@ -16,136 +16,138 @@ use Socket qw/ CRLF /; BEGIN { use FindBin; chdir($FindBin::Bin); } -use _common; +use lib 'lib'; +use Test::Nginx; +use Test::Nginx::SMTP; ############################################################################### select STDERR; $| = 1; select STDOUT; $| = 1; -start_nginx('smtp.conf'); +my $t = Test::Nginx->new()->run('smtp.conf'); ############################################################################### -my $s = smtp_connect(); -smtp_check(qr/^220 /, "greeting"); +my $s = Test::Nginx::SMTP->new(); +$s->check(qr/^220 /, "greeting"); -smtp_send('EHLO example.com'); -smtp_check(qr/^250 /, "ehlo"); +$s->send('EHLO example.com'); +$s->check(qr/^250 /, "ehlo"); -smtp_send('AUTH PLAIN ' . encode_base64("test\@example.com\0\0bad", '')); -smtp_check(qr/^5.. /, 'auth plain with bad password'); +$s->send('AUTH PLAIN ' . encode_base64("test\@example.com\0\0bad", '')); +$s->check(qr/^5.. /, 'auth plain with bad password'); -smtp_send('AUTH PLAIN ' . encode_base64("test\@example.com\0\0secret", '')); -smtp_ok('auth plain'); +$s->send('AUTH PLAIN ' . encode_base64("test\@example.com\0\0secret", '')); +$s->ok('auth plain'); # We are talking to backend from this point -smtp_send('MAIL FROM: SIZE=100'); -smtp_ok('mail from after auth'); +$s->send('MAIL FROM: SIZE=100'); +$s->ok('mail from after auth'); -smtp_send('RSET'); -smtp_ok('rset'); +$s->send('RSET'); +$s->ok('rset'); -smtp_send('MAIL FROM: SIZE=100'); -smtp_ok("idn mail from (example.test in russian)"); +$s->send('MAIL FROM: SIZE=100'); +$s->ok("idn mail from (example.test in russian)"); -smtp_send('QUIT'); -smtp_ok("quit"); +$s->send('QUIT'); +$s->ok("quit"); # Try auth plain with pipelining -$s = smtp_connect(); -smtp_check(qr/^220 /, "greeting"); +$s = Test::Nginx::SMTP->new(); +$s->check(qr/^220 /, "greeting"); -smtp_send('EHLO example.com'); -smtp_check(qr/^250 /, "ehlo"); +$s->send('EHLO example.com'); +$s->check(qr/^250 /, "ehlo"); -smtp_send('INVALID COMMAND WITH ARGUMENTS' . CRLF +$s->send('INVALID COMMAND WITH ARGUMENTS' . CRLF . 'RSET'); -smtp_read(); -smtp_ok('pipelined rset after invalid command'); +$s->read(); +$s->ok('pipelined rset after invalid command'); -smtp_send('AUTH PLAIN ' +$s->send('AUTH PLAIN ' . encode_base64("test\@example.com\0\0bad", '') . CRLF . 'MAIL FROM: SIZE=100'); -smtp_read(); -smtp_ok('mail from after failed pipelined auth'); +$s->read(); +$s->ok('mail from after failed pipelined auth'); -smtp_send('AUTH PLAIN ' +$s->send('AUTH PLAIN ' . encode_base64("test\@example.com\0\0secret", '') . CRLF . 'MAIL FROM: SIZE=100'); -smtp_read(); -smtp_ok('mail from after pipelined auth'); +$s->read(); +$s->ok('mail from after pipelined auth'); # Try auth none -$s = smtp_connect(); -smtp_check(qr/^220 /, "greeting"); +$s = Test::Nginx::SMTP->new(); +$s->check(qr/^220 /, "greeting"); -smtp_send('EHLO example.com'); -smtp_check(qr/^250 /, "ehlo"); +$s->send('EHLO example.com'); +$s->check(qr/^250 /, "ehlo"); -smtp_send('MAIL FROM: SIZE=100'); -smtp_ok('auth none - mail from'); +$s->send('MAIL FROM: SIZE=100'); +$s->ok('auth none - mail from'); -smtp_send('RCPT TO:'); -smtp_ok('auth none - rcpt to'); +$s->send('RCPT TO:'); +$s->ok('auth none - rcpt to'); -smtp_send('RSET'); -smtp_ok('auth none - rset, should go to backend'); +$s->send('RSET'); +$s->ok('auth none - rset, should go to backend'); # Auth none with pipelining -$s = smtp_connect(); -smtp_check(qr/^220 /, "greeting"); +$s = Test::Nginx::SMTP->new(); +$s->check(qr/^220 /, "greeting"); -smtp_send('EHLO example.com'); -smtp_check(qr/^250 /, "ehlo"); +$s->send('EHLO example.com'); +$s->check(qr/^250 /, "ehlo"); -smtp_send('MAIL FROM: SIZE=100' . CRLF +$s->send('MAIL FROM: SIZE=100' . CRLF . 'RCPT TO:' . CRLF . 'RSET'); -smtp_ok('pipelined mail from'); +$s->ok('pipelined mail from'); -smtp_ok('pipelined rcpt to'); -smtp_ok('pipelined rset'); +$s->ok('pipelined rcpt to'); +$s->ok('pipelined rset'); # Connection must stay even if error returned to rcpt to command -$s = smtp_connect(); -smtp_read(); # skip greeting +$s = Test::Nginx::SMTP->new(); +$s->read(); # skip greeting -smtp_send('EHLO example.com'); -smtp_read(); # skip ehlo reply +$s->send('EHLO example.com'); +$s->read(); # skip ehlo reply -smtp_send('MAIL FROM: SIZE=100'); -smtp_read(); # skip mail from reply +$s->send('MAIL FROM: SIZE=100'); +$s->read(); # skip mail from reply -smtp_send('RCPT TO:'); -smtp_check(qr/^5.. /, "bad rcpt to"); +$s->send('RCPT TO:'); +$s->check(qr/^5.. /, "bad rcpt to"); -smtp_send('RCPT TO:'); -smtp_ok('good rcpt to'); +$s->send('RCPT TO:'); +$s->ok('good rcpt to'); # Make sure command splitted into many packets processed correctly -$s = smtp_connect(); -smtp_read(); +$s = Test::Nginx::SMTP->new(); +$s->read(); log_out('HEL'); $s->print('HEL'); -smtp_send('O example.com'); -smtp_ok('splitted command'); +$s->send('O example.com'); +$s->ok('splitted command'); # With smtp_greeting_delay session expected to be closed after first error # message if client sent something before greeting. Use 10026 port # configured with smtp_greeting_delay 0.1s to check this. -$s = smtp_connect(PeerPort => 10026); -smtp_send('HELO example.com'); -smtp_check(qr/^5.. /, "command before greeting - session must be rejected"); +$s = Test::Nginx::SMTP->new(PeerPort => 10026); +$s->send('HELO example.com'); +$s->check(qr/^5.. /, "command before greeting - session must be rejected"); ok($s->eof(), "session have to be closed"); ############################################################################### diff --git a/ssi-include-big.t b/ssi-include-big.t --- a/ssi-include-big.t +++ b/ssi-include-big.t @@ -13,23 +13,24 @@ use Test::More tests => 3; BEGIN { use FindBin; chdir($FindBin::Bin); } -use _common; +use lib 'lib'; +use Test::Nginx; ############################################################################### select STDERR; $| = 1; select STDOUT; $| = 1; -start_nginx('ssi-include-big.conf'); +my $t = Test::Nginx->new()->run('ssi-include-big.conf'); -write_file('c1.html', 'X' x 1023); -write_file('c2.html', 'X' x 1024); -write_file('c3.html', 'X' x 1025); -write_file('test1.html', '' . "\n" +$t->write_file('c1.html', 'X' x 1023); +$t->write_file('c2.html', 'X' x 1024); +$t->write_file('c3.html', 'X' x 1025); +$t->write_file('test1.html', '' . "\n" . ''); -write_file('test2.html', '' . "\n" +$t->write_file('test2.html', '' . "\n" . ''); -write_file('test3.html', '' . "\n" +$t->write_file('test3.html', '' . "\n" . ''); ###############################################################################