changeset 59:bc3351f157ef

Tests: add basic pop3 and imap tests.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 12 Jan 2009 06:08:05 +0300
parents d053b4bf6ec6
children 11e33ba0656a
files README imap.t lib/Test/Nginx/IMAP.pm lib/Test/Nginx/POP3.pm pop3.t
diffstat 5 files changed, 475 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/README
+++ b/README
@@ -10,7 +10,8 @@ nginx binary available as ../nginx/objs/
 Note: some tests may fail since they are for bugs not fixed in public code.
 
 Note: tests run nginx (and backend daemons if needed) listening on localhost.
-Currently this includes following ports: 8025, 8026, 8080, 8081.
+Currently this includes following ports: 8025, 8026, 8080, 8081, 8110, 8111,
+8143, 8144.
 
 Tests for memcached required memcached itself and Cache::Memcached to be
 installed.
new file mode 100644
--- /dev/null
+++ b/imap.t
@@ -0,0 +1,129 @@
+#!/usr/bin/perl
+
+# (C) Maxim Dounin
+
+# Tests for nginx mail imap module.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+use IO::Socket;
+use MIME::Base64;
+use Socket qw/ CRLF /;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+use Test::Nginx::IMAP;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()
+	->has('mail')->plan(8)
+	->run_daemon(\&Test::Nginx::IMAP::imap_test_daemon)
+	->write_file_expand('nginx.conf', <<'EOF')->run();
+
+master_process off;
+daemon         off;
+
+events {
+    worker_connections  1024;
+}
+
+mail {
+    proxy_pass_error_message  on;
+    auth_http  http://127.0.0.1:8080/mail/auth;
+
+    server {
+        listen     127.0.0.1:8143;
+        protocol   imap;
+        smtp_auth  login plain;
+    }
+}
+
+http {
+    access_log    off;
+
+    client_body_temp_path  %%TESTDIR%%/client_body_temp;
+    fastcgi_temp_path      %%TESTDIR%%/fastcgi_temp;
+    proxy_temp_path        %%TESTDIR%%/proxy_temp;
+
+    server {
+        listen       127.0.0.1:8080;
+        server_name  localhost;
+
+        location = /mail/auth {
+            set $reply ERROR;
+
+            if ($http_auth_smtp_to ~ example.com) {
+                set $reply OK;
+            }
+
+            set $userpass "$http_auth_user:$http_auth_pass";
+            if ($userpass ~ '^test@example.com:secret$') {
+                set $reply OK;
+            }
+
+            add_header Auth-Status $reply;
+            add_header Auth-Server 127.0.0.1;
+            add_header Auth-Port 8144;
+            add_header Auth-Wait 1;
+            return 204;
+        }
+    }
+}
+
+EOF
+
+###############################################################################
+
+my $s = Test::Nginx::IMAP->new();
+$s->ok('greeting');
+
+# auth plain
+
+$s->send('1 AUTHENTICATE PLAIN ' . encode_base64("\0test\@example.com\0bad", ''));
+$s->check(qr/^\S+ NO/, 'auth plain with bad password');
+
+$s->send('1 AUTHENTICATE PLAIN ' . encode_base64("\0test\@example.com\0secret", ''));
+$s->ok('auth plain');
+
+# auth login simple
+
+$s = Test::Nginx::IMAP->new();
+$s->read();
+
+$s->send('1 AUTHENTICATE LOGIN');
+$s->check(qr/\+ VXNlcm5hbWU6/, 'auth login username challenge');
+
+$s->send(encode_base64('test@example.com', ''));
+$s->check(qr/\+ UGFzc3dvcmQ6/, 'auth login password challenge');
+
+$s->send(encode_base64('secret', ''));
+$s->ok('auth login simple');
+
+# auth login with username
+
+TODO: {
+local $TODO = 'not supported yet';
+
+$s = Test::Nginx::IMAP->new();
+$s->read();
+
+$s->send('1 AUTHENTICATE LOGIN ' . encode_base64('test@example.com', ''));
+$s->check(qr/\+ UGFzc3dvcmQ6/, 'auth login with username password challenge');
+
+$s->send(encode_base64('secret', ''));
+$s->ok('auth login with username');
+
+}
+
+###############################################################################
new file mode 100644
--- /dev/null
+++ b/lib/Test/Nginx/IMAP.pm
@@ -0,0 +1,109 @@
+package Test::Nginx::IMAP;
+
+# (C) Maxim Dounin
+
+# Module for nginx imap tests.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More qw//;
+use IO::Socket;
+use Socket qw/ CRLF /;
+
+use Test::Nginx;
+
+use base qw/ IO::Socket::INET /;
+
+sub new {
+	my $class = shift;
+
+	my $self = return $class->SUPER::new(
+		Proto => "tcp",
+		PeerAddr => "127.0.0.1:8143",
+		@_
+	)
+		or die "Can't connect to nginx: $!\n";
+
+	$self->autoflush(1);
+
+	return $self;
+}
+
+sub send {
+	my ($self, $cmd) = @_;
+	log_out($cmd);
+	$self->print($cmd . CRLF);
+}
+
+sub read {
+	my ($self) = @_;
+	eval {
+		alarm(2);
+		local $SIG{ALRM} = sub { die "alarm\n" };
+		while (<$self>) {
+			log_in($_);
+			# XXX
+			next if m/^\d\d\d-/;
+			last;
+		}
+		alarm(0);
+	};
+	alarm(0);
+	if ($@) {
+		return undef;
+	}
+	return $_;
+}
+
+sub check {
+	my ($self, $regex, $name) = @_;
+	Test::More->builder->like($self->read(), $regex, $name);
+}
+
+sub ok {
+	my $self = shift; 
+	Test::More->builder->like($self->read(), qr/^\S+ OK/, @_);
+}
+
+###############################################################################
+
+sub imap_test_daemon {
+	my $server = IO::Socket::INET->new(
+		Proto => 'tcp',
+		LocalAddr => '127.0.0.1:8144',
+		Listen => 5,
+		Reuse => 1
+	)
+		or die "Can't create listening socket: $!\n";
+
+	while (my $client = $server->accept()) {
+		$client->autoflush(1);
+		print $client "* OK fake imap server ready" . CRLF;
+
+		while (<$client>) {
+			my $tag = '';
+
+			$tag = $1 if m/^(\S+)/;
+			s/^(\S+)\s+//;
+
+			if (/^logout/i) {
+				print $client $tag . ' OK logout ok' . CRLF;
+			} elsif (/^login /i) {
+				print $client $tag . ' OK login ok' . CRLF;
+			} else {
+				print $client $tag . ' ERR unknown command' . CRLF;
+			}
+                }
+
+		close $client;
+	}
+}
+
+###############################################################################
+
+1;
+
+###############################################################################
new file mode 100644
--- /dev/null
+++ b/lib/Test/Nginx/POP3.pm
@@ -0,0 +1,106 @@
+package Test::Nginx::POP3;
+
+# (C) Maxim Dounin
+
+# Module for nginx pop3 tests.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More qw//;
+use IO::Socket;
+use Socket qw/ CRLF /;
+
+use Test::Nginx;
+
+use base qw/ IO::Socket::INET /;
+
+sub new {
+	my $class = shift;
+
+	my $self = return $class->SUPER::new(
+		Proto => "tcp",
+		PeerAddr => "127.0.0.1:8110",
+		@_
+	)
+		or die "Can't connect to nginx: $!\n";
+
+	$self->autoflush(1);
+
+	return $self;
+}
+
+sub send {
+	my ($self, $cmd) = @_;
+	log_out($cmd);
+	$self->print($cmd . CRLF);
+}
+
+sub read {
+	my ($self) = @_;
+	eval {
+		alarm(2);
+		local $SIG{ALRM} = sub { die "alarm\n" };
+		while (<$self>) {
+			log_in($_);
+			# XXX
+			next if m/^\d\d\d-/;
+			last;
+		}
+		alarm(0);
+	};
+	alarm(0);
+	if ($@) {
+		return undef;
+	}
+	return $_;
+}
+
+sub check {
+	my ($self, $regex, $name) = @_;
+	Test::More->builder->like($self->read(), $regex, $name);
+}
+
+sub ok {
+	my $self = shift; 
+	Test::More->builder->like($self->read(), qr/^\+OK/, @_);
+}
+
+###############################################################################
+
+sub pop3_test_daemon {
+	my $server = IO::Socket::INET->new(
+		Proto => 'tcp',
+		LocalAddr => '127.0.0.1:8111',
+		Listen => 5,
+		Reuse => 1
+	)
+		or die "Can't create listening socket: $!\n";
+
+	while (my $client = $server->accept()) {
+		$client->autoflush(1);
+		print $client "+OK fake pop3 server ready" . CRLF;
+
+		while (<$client>) {
+			if (/^quit/i) {
+				print $client '+OK quit ok' . CRLF;
+			} elsif (/^user test\@example.com/i) {
+				print $client '+OK user ok' . CRLF;
+			} elsif (/^pass secret/i) {
+				print $client '+OK pass ok' . CRLF;
+			} else {
+				print $client "-ERR unknown command" . CRLF;
+			}
+                }
+
+		close $client;
+	}
+}
+
+###############################################################################
+
+1;
+
+###############################################################################
new file mode 100644
--- /dev/null
+++ b/pop3.t
@@ -0,0 +1,129 @@
+#!/usr/bin/perl
+
+# (C) Maxim Dounin
+
+# Tests for nginx mail pop3 module.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+use IO::Socket;
+use MIME::Base64;
+use Socket qw/ CRLF /;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+use Test::Nginx::POP3;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()
+	->has('mail')->plan(8)
+	->run_daemon(\&Test::Nginx::POP3::pop3_test_daemon)
+	->write_file_expand('nginx.conf', <<'EOF')->run();
+
+master_process off;
+daemon         off;
+
+events {
+    worker_connections  1024;
+}
+
+mail {
+    proxy_pass_error_message  on;
+    auth_http  http://127.0.0.1:8080/mail/auth;
+
+    server {
+        listen     127.0.0.1:8110;
+        protocol   pop3;
+        smtp_auth  login plain;
+    }
+}
+
+http {
+    access_log    off;
+
+    client_body_temp_path  %%TESTDIR%%/client_body_temp;
+    fastcgi_temp_path      %%TESTDIR%%/fastcgi_temp;
+    proxy_temp_path        %%TESTDIR%%/proxy_temp;
+
+    server {
+        listen       127.0.0.1:8080;
+        server_name  localhost;
+
+        location = /mail/auth {
+            set $reply ERROR;
+
+            if ($http_auth_smtp_to ~ example.com) {
+                set $reply OK;
+            }
+
+            set $userpass "$http_auth_user:$http_auth_pass";
+            if ($userpass ~ '^test@example.com:secret$') {
+                set $reply OK;
+            }
+
+            add_header Auth-Status $reply;
+            add_header Auth-Server 127.0.0.1;
+            add_header Auth-Port 8111;
+            add_header Auth-Wait 1;
+            return 204;
+        }
+    }
+}
+
+EOF
+
+###############################################################################
+
+my $s = Test::Nginx::POP3->new();
+$s->ok('greeting');
+
+# auth plain
+
+$s->send('AUTH PLAIN ' . encode_base64("\0test\@example.com\0bad", ''));
+$s->check(qr/^-ERR/, 'auth plain with bad password');
+
+$s->send('AUTH PLAIN ' . encode_base64("\0test\@example.com\0secret", ''));
+$s->ok('auth plain');
+
+# auth login simple
+
+$s = Test::Nginx::POP3->new();
+$s->read();
+
+$s->send('AUTH LOGIN');
+$s->check(qr/\+ VXNlcm5hbWU6/, 'auth login username challenge');
+
+$s->send(encode_base64('test@example.com', ''));
+$s->check(qr/\+ UGFzc3dvcmQ6/, 'auth login password challenge');
+
+$s->send(encode_base64('secret', ''));
+$s->ok('auth login simple');
+
+# auth login with username
+
+TODO: {
+local $TODO = 'not supported yet';
+
+$s = Test::Nginx::POP3->new();
+$s->read();
+
+$s->send('AUTH LOGIN ' . encode_base64('test@example.com', ''));
+$s->check(qr/\+ UGFzc3dvcmQ6/, 'auth login with username password challenge');
+
+$s->send(encode_base64('secret', ''));
+$s->ok('auth login with username');
+
+}
+
+###############################################################################