changeset 14:d4b74207a627

Tests: refactor common functions. Let it be something more structured, avoid globals.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 12 Sep 2008 20:50:35 +0400
parents e8edb765595d
children c6c36d7a4d90
files _common.pm lib/Test/Nginx.pm lib/Test/Nginx/SMTP.pm smtp.t ssi-include-big.t
diffstat 4 files changed, 128 insertions(+), 261 deletions(-) [+]
line wrap: on
line diff
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;
 
 ###############################################################################
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 /, @_);
 }
 
 ###############################################################################
--- 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:<test@example.com> SIZE=100');
-smtp_ok('mail from after auth');
+$s->send('MAIL FROM:<test@example.com> SIZE=100');
+$s->ok('mail from after auth');
 
-smtp_send('RSET');
-smtp_ok('rset');
+$s->send('RSET');
+$s->ok('rset');
 
-smtp_send('MAIL FROM:<test@xn--e1afmkfd.xn--80akhbyknj4f> SIZE=100');
-smtp_ok("idn mail from (example.test in russian)");
+$s->send('MAIL FROM:<test@xn--e1afmkfd.xn--80akhbyknj4f> 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:<test@example.com> 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:<test@example.com> 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:<test@example.com> SIZE=100');
-smtp_ok('auth none - mail from');
+$s->send('MAIL FROM:<test@example.com> SIZE=100');
+$s->ok('auth none - mail from');
 
-smtp_send('RCPT TO:<test@example.com>');
-smtp_ok('auth none - rcpt to');
+$s->send('RCPT TO:<test@example.com>');
+$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:<test@example.com> SIZE=100' . CRLF
+$s->send('MAIL FROM:<test@example.com> SIZE=100' . CRLF
 	. 'RCPT TO:<test@example.com>' . 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:<test@example.com> SIZE=100');
-smtp_read(); # skip mail from reply
+$s->send('MAIL FROM:<test@example.com> SIZE=100');
+$s->read(); # skip mail from reply
 
-smtp_send('RCPT TO:<example.com>');
-smtp_check(qr/^5.. /, "bad rcpt to");
+$s->send('RCPT TO:<example.com>');
+$s->check(qr/^5.. /, "bad rcpt to");
 
-smtp_send('RCPT TO:<test@example.com>');
-smtp_ok('good rcpt to');
+$s->send('RCPT TO:<test@example.com>');
+$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");
 
 ###############################################################################
--- 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', '<!--#include virtual="/proxy/blah" -->' . "\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', '<!--#include virtual="/proxy/blah" -->' . "\n"
 	. '<!--#include virtual="/c1.html" -->');
-write_file('test2.html', '<!--#include virtual="/proxy/blah" -->' . "\n"
+$t->write_file('test2.html', '<!--#include virtual="/proxy/blah" -->' . "\n"
 	. '<!--#include virtual="/c2.html" -->');
-write_file('test3.html', '<!--#include virtual="/proxy/blah" -->' . "\n"
+$t->write_file('test3.html', '<!--#include virtual="/proxy/blah" -->' . "\n"
 	. '<!--#include virtual="/c3.html" -->');
 
 ###############################################################################