From: Ashley Pond V Date: Wed, 19 Aug 2009 05:24:20 +0000 (+0000) Subject: Splitting up the live tests. A moo. X-Git-Tag: v0.14~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Authentication-Credential-OpenID.git;a=commitdiff_plain;h=19439725f0676426a2f0d41463b68dee5dbb3e51 Splitting up the live tests. A moo. --- diff --git a/t/Consumer/lib/TestApp.pm b/t/Consumer/lib/TestApp.pm new file mode 100644 index 0000000..669b76c --- /dev/null +++ b/t/Consumer/lib/TestApp.pm @@ -0,0 +1,74 @@ +package TestApp; + +use strict; +use warnings; + +use Catalyst::Runtime '5.70'; + +use Catalyst qw( + -Debug + ConfigLoader + Authentication + Session + Session::Store::FastMmap + Session::State::Cookie + ); + +our $VERSION = '0.00001'; + +__PACKAGE__->config + ( name => "TestApp", + session => { + storage => "/tmp/" . __PACKAGE__ . "-" . $VERSION, + }, + startup_time => time(), + "Plugin::Authentication" => { + default_realm => "members", + realms => { + members => { + credential => { + class => "Password", + password_field => "password", + password_type => "clear" + }, + store => { + class => "Minimal", + users => { + paco => { + password => "l4s4v3n7ur45", + }, + } + } + }, + openid => { + # ua_class => "LWPx::ParanoidAgent", + ua_class => "LWP::UserAgent", + ua_args => { + whitelisted_hosts => [qw/ 127.0.0.1 localhost /], + timeout => 10, + }, + extension_args => [ + 'http://openid.net/extensions/sreg/1.1', + { + required => 'email', + optional => 'fullname,nickname,timezone', + }, + ], + debug => 1, + credential => { + class => "OpenID", +#DOES NOTHING use_session => 1, + store => { + class => "OpenID", + }, + }, + }, + }, + }, + ); + +__PACKAGE__->setup(); + +1; + +__END__ diff --git a/t/Consumer/lib/TestApp/Controller/Root.pm b/t/Consumer/lib/TestApp/Controller/Root.pm new file mode 100644 index 0000000..5d61784 --- /dev/null +++ b/t/Consumer/lib/TestApp/Controller/Root.pm @@ -0,0 +1,148 @@ +package TestApp::Controller::Root; + +use strict; +use warnings; +no warnings "uninitialized"; +use base 'Catalyst::Controller'; +use Net::OpenID::Server; + +__PACKAGE__->config->{namespace} = ''; + +=head1 NAME + +TestApp::Controller::Root - Root Controller for TestApp. + +=head1 DESCRIPTION + +D'er... testing. Has an OpenID provider to test the OpenID credential against. + +=cut + +sub provider : Local { + my ( $self, $c, $username ) = @_; + + my $nos = Net::OpenID::Server + ->new( + get_args => $c->req->query_params, + post_args => $c->req->body_params, + get_user => sub { $c->user }, + is_identity => sub { + my ( $user, $identity_url ) = @_; + return unless $user; + my ( $check ) = $identity_url =~ /(\w+)\z/; + return $check eq $user->id; # simple auth here + }, + is_trusted => sub { + my ( $user, $trust_root, $is_identity ) = @_; + return $is_identity; # enough that they passed is_identity + }, + setup_url => $c->uri_for($c->req->path, {moo => "setup"}), + server_secret => $c->config->{startup_time}, + ); + + # From your OpenID server endpoint: + + my ( $type, $data ) = $nos->handle_page; + + if ($type eq "redirect") + { + $c->res->redirect($data); + } + elsif ($type eq "setup") + { + my %setup_opts = %{$data}; + $c->res->body(<<""); +You're not signed in so you can't be verified. +Sign in | OpenId. + + # it's then your job to redirect them at the end to "return_to" + # (or whatever you've named it in setup_map) + } + else + { + $c->res->content_type($type); + if ( $username ) + { + my $server_uri = $c->uri_for($c->req->path); + $data =~ s,(?=),,; + } + $c->res->body($data); + } +} + +sub logout : Local { + my($self, $c) = @_; + $c->logout if $c->user_exists; + $c->delete_session(); + $c->res->redirect($c->uri_for("/")); +} + +sub login : Local { + my($self, $c) = @_; + + if ( $c->req->method eq 'POST' + and + $c->authenticate({ username => $c->req->body_params->{username}, + password => $c->req->body_params->{password} }) ) + { +# $c->res->body("You are signed in!"); + $c->res->redirect($c->uri_for("/")); + } + else + { + my $action = $c->req->uri->path; + $c->res->body(<<""); +
+ + + +
+ + + } +} + +sub signin_openid : Local { + my($self, $c) = @_; + + if ( $c->authenticate({}, "openid") ) + { + $c->res->body("You did it with OpenID!"); + } + else + { + my $action = $c->req->uri->path; + $c->res->body(<<""); +
+ + +
+ + } +} + +sub default : Private { + my ( $self, $c ) = @_; + $c->response->body( + join(" ", + "You are", + $c->user ? "" : "not", + "signed in.
", + $c->user ? ( $c->user->id || %{$c->user} ) : 'Sign in | OpenId.' + ) + ); +} + +sub end : Private { + my ( $self, $c ) = @_; + $c->response->content_type("text/html"); +} + +=head1 LICENSE + +This library is free software, you can redistribute it and modify +it under the same terms as Perl itself. + +=cut + +1; diff --git a/t/Consumer/script/testapp_server.pl b/t/Consumer/script/testapp_server.pl new file mode 100755 index 0000000..25efa8b --- /dev/null +++ b/t/Consumer/script/testapp_server.pl @@ -0,0 +1,160 @@ +#!/usr/bin/env perl + +BEGIN { + $ENV{CATALYST_ENGINE} ||= 'HTTP'; + $ENV{CATALYST_SCRIPT_GEN} = 39; + require Catalyst::Engine::HTTP; +} + +use strict; +use warnings; +use Getopt::Long; +use Pod::Usage; +use FindBin; +use lib "$FindBin::Bin/../lib"; + +my $debug = 0; +my $fork = 0; +my $help = 0; +my $host = undef; +my $port = $ENV{TESTAPP_PORT} || $ENV{CATALYST_PORT} || 3000; +my $keepalive = 0; +my $restart = $ENV{TESTAPP_RELOAD} || $ENV{CATALYST_RELOAD} || 0; +my $background = 0; +my $pidfile = undef; + +my $check_interval; +my $file_regex; +my $watch_directory; +my $follow_symlinks; + +my @argv = @ARGV; + +GetOptions( + 'debug|d' => \$debug, + 'fork|f' => \$fork, + 'help|?' => \$help, + 'host=s' => \$host, + 'port|p=s' => \$port, + 'keepalive|k' => \$keepalive, + 'restart|r' => \$restart, + 'restartdelay|rd=s' => \$check_interval, + 'restartregex|rr=s' => \$file_regex, + 'restartdirectory=s@' => \$watch_directory, + 'followsymlinks' => \$follow_symlinks, + 'background' => \$background, + 'pidfile=s' => \$pidfile, +); + +pod2usage(1) if $help; + +if ( $debug ) { + $ENV{CATALYST_DEBUG} = 1; +} + +# If we load this here, then in the case of a restarter, it does not +# need to be reloaded for each restart. +require Catalyst; + +# If this isn't done, then the Catalyst::Devel tests for the restarter +# fail. +$| = 1 if $ENV{HARNESS_ACTIVE}; + +my $runner = sub { + # This is require instead of use so that the above environment + # variables can be set at runtime. + require TestApp; + + TestApp->run( + $port, $host, + { + argv => \@argv, + 'fork' => $fork, + keepalive => $keepalive, + background => $background, + pidfile => $pidfile, + } + ); +}; + +if ( $restart ) { + die "Cannot run in the background and also watch for changed files.\n" + if $background; + + require Catalyst::Restarter; + + my $subclass = Catalyst::Restarter->pick_subclass; + + my %args; + $args{follow_symlinks} = 1 + if $follow_symlinks; + $args{directories} = $watch_directory + if defined $watch_directory; + $args{sleep_interval} = $check_interval + if defined $check_interval; + $args{filter} = qr/$file_regex/ + if defined $file_regex; + + my $restarter = $subclass->new( + %args, + start_sub => $runner, + argv => \@argv, + ); + + $restarter->run_and_watch; +} +else { + $runner->(); +} + +1; + +=head1 NAME + +testapp_server.pl - Catalyst Testserver + +=head1 SYNOPSIS + +testapp_server.pl [options] + + Options: + -d -debug force debug mode + -f -fork handle each request in a new process + (defaults to false) + -? -help display this help and exits + -host host (defaults to all) + -p -port port (defaults to 3000) + -k -keepalive enable keep-alive connections + -r -restart restart when files get modified + (defaults to false) + -rd -restartdelay delay between file checks + (ignored if you have Linux::Inotify2 installed) + -rr -restartregex regex match files that trigger + a restart when modified + (defaults to '\.yml$|\.yaml$|\.conf|\.pm$') + -restartdirectory the directory to search for + modified files, can be set mulitple times + (defaults to '[SCRIPT_DIR]/..') + -follow_symlinks follow symlinks in search directories + (defaults to false. this is a no-op on Win32) + -background run the process in the background + -pidfile specify filename for pid file + + See also: + perldoc Catalyst::Manual + perldoc Catalyst::Manual::Intro + +=head1 DESCRIPTION + +Run a Catalyst Testserver for this application. + +=head1 AUTHORS + +Catalyst Contributors, see Catalyst.pm + +=head1 COPYRIGHT + +This library is free software. You can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/t/Provider/lib/TestApp.pm b/t/Provider/lib/TestApp.pm new file mode 100644 index 0000000..7544c4c --- /dev/null +++ b/t/Provider/lib/TestApp.pm @@ -0,0 +1,74 @@ +package TestApp; + +use strict; +use warnings; + +use Catalyst::Runtime '5.70'; + +use Catalyst qw( + -Debug + ConfigLoader + Authentication + Session + Session::Store::FastMmap + Session::State::Cookie + ); + +our $VERSION = '0.00002'; + +__PACKAGE__->config + ( name => "TestApp", + session => { + storage => "/tmp/" . __PACKAGE__ . "-" . $VERSION, + }, + startup_time => time(), + "Plugin::Authentication" => { + default_realm => "members", + realms => { + members => { + credential => { + class => "Password", + password_field => "password", + password_type => "clear" + }, + store => { + class => "Minimal", + users => { + paco => { + password => "l4s4v3n7ur45", + }, + } + } + }, + openid => { + #ua_class => "LWPx::ParanoidAgent", + ua_class => "LWP::UserAgent", + ua_args => { + whitelisted_hosts => [qw/ 127.0.0.1 localhost /], + timeout => 10, + }, + extension_args => [ + 'http://openid.net/extensions/sreg/1.1', + { + required => 'email', + optional => 'fullname,nickname,timezone', + }, + ], + debug => 1, + credential => { + class => "OpenID", +#DOES NOTHING use_session => 1, + store => { + class => "OpenID", + }, + }, + }, + }, + }, + ); + +__PACKAGE__->setup(); + +1; + +__END__ diff --git a/t/Provider/lib/TestApp/Controller/Root.pm b/t/Provider/lib/TestApp/Controller/Root.pm new file mode 100644 index 0000000..5d61784 --- /dev/null +++ b/t/Provider/lib/TestApp/Controller/Root.pm @@ -0,0 +1,148 @@ +package TestApp::Controller::Root; + +use strict; +use warnings; +no warnings "uninitialized"; +use base 'Catalyst::Controller'; +use Net::OpenID::Server; + +__PACKAGE__->config->{namespace} = ''; + +=head1 NAME + +TestApp::Controller::Root - Root Controller for TestApp. + +=head1 DESCRIPTION + +D'er... testing. Has an OpenID provider to test the OpenID credential against. + +=cut + +sub provider : Local { + my ( $self, $c, $username ) = @_; + + my $nos = Net::OpenID::Server + ->new( + get_args => $c->req->query_params, + post_args => $c->req->body_params, + get_user => sub { $c->user }, + is_identity => sub { + my ( $user, $identity_url ) = @_; + return unless $user; + my ( $check ) = $identity_url =~ /(\w+)\z/; + return $check eq $user->id; # simple auth here + }, + is_trusted => sub { + my ( $user, $trust_root, $is_identity ) = @_; + return $is_identity; # enough that they passed is_identity + }, + setup_url => $c->uri_for($c->req->path, {moo => "setup"}), + server_secret => $c->config->{startup_time}, + ); + + # From your OpenID server endpoint: + + my ( $type, $data ) = $nos->handle_page; + + if ($type eq "redirect") + { + $c->res->redirect($data); + } + elsif ($type eq "setup") + { + my %setup_opts = %{$data}; + $c->res->body(<<""); +You're not signed in so you can't be verified. +Sign in | OpenId. + + # it's then your job to redirect them at the end to "return_to" + # (or whatever you've named it in setup_map) + } + else + { + $c->res->content_type($type); + if ( $username ) + { + my $server_uri = $c->uri_for($c->req->path); + $data =~ s,(?=),,; + } + $c->res->body($data); + } +} + +sub logout : Local { + my($self, $c) = @_; + $c->logout if $c->user_exists; + $c->delete_session(); + $c->res->redirect($c->uri_for("/")); +} + +sub login : Local { + my($self, $c) = @_; + + if ( $c->req->method eq 'POST' + and + $c->authenticate({ username => $c->req->body_params->{username}, + password => $c->req->body_params->{password} }) ) + { +# $c->res->body("You are signed in!"); + $c->res->redirect($c->uri_for("/")); + } + else + { + my $action = $c->req->uri->path; + $c->res->body(<<""); +
+ + + +
+ + + } +} + +sub signin_openid : Local { + my($self, $c) = @_; + + if ( $c->authenticate({}, "openid") ) + { + $c->res->body("You did it with OpenID!"); + } + else + { + my $action = $c->req->uri->path; + $c->res->body(<<""); +
+ + +
+ + } +} + +sub default : Private { + my ( $self, $c ) = @_; + $c->response->body( + join(" ", + "You are", + $c->user ? "" : "not", + "signed in.
", + $c->user ? ( $c->user->id || %{$c->user} ) : 'Sign in | OpenId.' + ) + ); +} + +sub end : Private { + my ( $self, $c ) = @_; + $c->response->content_type("text/html"); +} + +=head1 LICENSE + +This library is free software, you can redistribute it and modify +it under the same terms as Perl itself. + +=cut + +1; diff --git a/t/Provider/script/testapp_server.pl b/t/Provider/script/testapp_server.pl new file mode 100755 index 0000000..25efa8b --- /dev/null +++ b/t/Provider/script/testapp_server.pl @@ -0,0 +1,160 @@ +#!/usr/bin/env perl + +BEGIN { + $ENV{CATALYST_ENGINE} ||= 'HTTP'; + $ENV{CATALYST_SCRIPT_GEN} = 39; + require Catalyst::Engine::HTTP; +} + +use strict; +use warnings; +use Getopt::Long; +use Pod::Usage; +use FindBin; +use lib "$FindBin::Bin/../lib"; + +my $debug = 0; +my $fork = 0; +my $help = 0; +my $host = undef; +my $port = $ENV{TESTAPP_PORT} || $ENV{CATALYST_PORT} || 3000; +my $keepalive = 0; +my $restart = $ENV{TESTAPP_RELOAD} || $ENV{CATALYST_RELOAD} || 0; +my $background = 0; +my $pidfile = undef; + +my $check_interval; +my $file_regex; +my $watch_directory; +my $follow_symlinks; + +my @argv = @ARGV; + +GetOptions( + 'debug|d' => \$debug, + 'fork|f' => \$fork, + 'help|?' => \$help, + 'host=s' => \$host, + 'port|p=s' => \$port, + 'keepalive|k' => \$keepalive, + 'restart|r' => \$restart, + 'restartdelay|rd=s' => \$check_interval, + 'restartregex|rr=s' => \$file_regex, + 'restartdirectory=s@' => \$watch_directory, + 'followsymlinks' => \$follow_symlinks, + 'background' => \$background, + 'pidfile=s' => \$pidfile, +); + +pod2usage(1) if $help; + +if ( $debug ) { + $ENV{CATALYST_DEBUG} = 1; +} + +# If we load this here, then in the case of a restarter, it does not +# need to be reloaded for each restart. +require Catalyst; + +# If this isn't done, then the Catalyst::Devel tests for the restarter +# fail. +$| = 1 if $ENV{HARNESS_ACTIVE}; + +my $runner = sub { + # This is require instead of use so that the above environment + # variables can be set at runtime. + require TestApp; + + TestApp->run( + $port, $host, + { + argv => \@argv, + 'fork' => $fork, + keepalive => $keepalive, + background => $background, + pidfile => $pidfile, + } + ); +}; + +if ( $restart ) { + die "Cannot run in the background and also watch for changed files.\n" + if $background; + + require Catalyst::Restarter; + + my $subclass = Catalyst::Restarter->pick_subclass; + + my %args; + $args{follow_symlinks} = 1 + if $follow_symlinks; + $args{directories} = $watch_directory + if defined $watch_directory; + $args{sleep_interval} = $check_interval + if defined $check_interval; + $args{filter} = qr/$file_regex/ + if defined $file_regex; + + my $restarter = $subclass->new( + %args, + start_sub => $runner, + argv => \@argv, + ); + + $restarter->run_and_watch; +} +else { + $runner->(); +} + +1; + +=head1 NAME + +testapp_server.pl - Catalyst Testserver + +=head1 SYNOPSIS + +testapp_server.pl [options] + + Options: + -d -debug force debug mode + -f -fork handle each request in a new process + (defaults to false) + -? -help display this help and exits + -host host (defaults to all) + -p -port port (defaults to 3000) + -k -keepalive enable keep-alive connections + -r -restart restart when files get modified + (defaults to false) + -rd -restartdelay delay between file checks + (ignored if you have Linux::Inotify2 installed) + -rr -restartregex regex match files that trigger + a restart when modified + (defaults to '\.yml$|\.yaml$|\.conf|\.pm$') + -restartdirectory the directory to search for + modified files, can be set mulitple times + (defaults to '[SCRIPT_DIR]/..') + -follow_symlinks follow symlinks in search directories + (defaults to false. this is a no-op on Win32) + -background run the process in the background + -pidfile specify filename for pid file + + See also: + perldoc Catalyst::Manual + perldoc Catalyst::Manual::Intro + +=head1 DESCRIPTION + +Run a Catalyst Testserver for this application. + +=head1 AUTHORS + +Catalyst Contributors, see Catalyst.pm + +=head1 COPYRIGHT + +This library is free software. You can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/t/live_app.t b/t/live-app.t similarity index 56% rename from t/live_app.t rename to t/live-app.t index db6e92b..6d080ed 100644 --- a/t/live_app.t +++ b/t/live-app.t @@ -1,5 +1,4 @@ -#!perl - +#!/usr/bin/env perl use strict; use warnings; @@ -8,56 +7,64 @@ use IO::Socket; use Test::More; use Test::WWW::Mechanize; -# plan skip_all => 'set TEST_HTTP to enable this test' unless $ENV{TEST_HTTP}; +plan skip_all => 'set TEST_HTTP to enable this test' unless $ENV{TEST_HTTP}; eval "use Catalyst::Devel 1.0"; plan skip_all => 'Catalyst::Devel required' if $@; -plan tests => 17; +plan "no_plan"; +# plan tests => 17; -# How long to wait for test server to start and timeout for UA. -my $seconds = 30; +# One port for consumer app, one for provider. +my $consumer_port = 10000 + int rand(1 + 10000); +my $provider_port = $consumer_port; +$provider_port = 10000 + int rand(1 + 10000) until $consumer_port != $provider_port; + +my $provider_pipe = "perl -I$FindBin::Bin/../lib -I$FindBin::Bin/Provider/lib $FindBin::Bin/Provider/script/testapp_server.pl -p $consumer_port |"; -# Spawn the standalone HTTP server. -my $port = 30000 + int rand(1 + 10000); +my $consumer_pipe = "perl -I$FindBin::Bin/../lib -I$FindBin::Bin/Consumer/lib $FindBin::Bin/Consumer/script/testapp_server.pl -p $provider_port |"; - my $pipe = "perl -I$FindBin::Bin/../lib -I$FindBin::Bin/TestApp/lib $FindBin::Bin/TestApp/script/testapp_server.pl -fork -port $port |"; +my $provider_pid = open my $provider, $provider_pipe + or die "Unable to spawn standalone HTTP server for Provider: $!"; -# my $pipe = "perl -I$FindBin::Bin/../lib -I$FindBin::Bin/TestApp/lib $FindBin::Bin/TestApp/script/testapp_server.pl -f -port $port 2>&1 |"; +diag("Started Provider with pid $provider_pid"); -my $pid = open my $server, $pipe - or die "Unable to spawn standalone HTTP server: $!"; +my $consumer_pid = open my $consumer, $consumer_pipe + or die "Unable to spawn standalone HTTP server for Consumer: $!"; -diag("Waiting (up to $seconds seconds) for server to start..."); +diag("Started Consumer with pid $consumer_pid"); + +# How long to wait for test server to start and timeout for UA. +my $seconds = 15; + + +diag("Waiting (up to $seconds seconds) for application servers to start..."); eval { - local $SIG{ALRM} = sub { die "Server took too long to start\n" }; # NB: \n required + local $SIG{ALRM} = sub { die "Servers took too long to start\n" }; # NB: \n required alarm($seconds); - - while ( check_port( 'localhost', $port ) != 1 ) { - sleep 1; - } + sleep 1 while check_port( 'localhost', $provider_port ) != 1; + sleep 1 while check_port( 'localhost', $consumer_port ) != 1; alarm(0) }; if ( $@ ) { - kill 'INT', $pid; - close $server; - die "Could not run test: $@\n$pipe"; + shut_down(); + die "Could not run test: $@"; } - -my $root = $ENV{CATALYST_SERVER} = "http://localhost:$port"; -# Tests start -------------------------------------------- -ok("Started"); +my $root = $ENV{CATALYST_SERVER} = "http://localhost:$consumer_port"; +my $openid_server = "http://localhost:$provider_port"; +# Tests start -------------------------------------------- +diag("Started...") if $ENV{TEST_VERBOSE}; my $mech = Test::WWW::Mechanize->new(timeout => $seconds); $mech->get_ok($root, "GET $root"); $mech->content_contains("not signed in", "Content looks right"); -$mech->get_ok("$root/login", "GET $root/login"); +$mech->get_ok("$openid_server/login", "GET $root/login"); # diag($mech->content); @@ -74,7 +81,7 @@ $mech->get_ok("$root/signin_openid", "GET $root/signin_openid"); $mech->content_contains("Sign in with OpenID", "Content looks right"); -my $claimed_uri = "$root/provider/paco"; +my $claimed_uri = "$openid_server/provider/paco"; $mech->submit_form_ok({ form_name => "openid", fields => { openid_identifier => $claimed_uri, @@ -87,8 +94,7 @@ $mech->content_contains("You did it with OpenID!", $mech->get_ok($root, "GET $root"); -$mech->content_contains("provider/paco", "OpenID signed in"); -#$mech->content_contains("paco", "OpenID signed in as paco"); +$mech->content_contains("provider/paco", "OpenID info is in the user"); # can't be verified @@ -107,14 +113,18 @@ $mech->submit_form_ok({ form_name => "openid", $mech->content_contains("can't be verified", "Proper failure for unauthenticated memember."); -# Tests end ---------------------------------------------- - -# shut it down -kill 'INT', $pid; -close $server; +shut_down(); exit 0; +# Tests end ---------------------------------------------- + +sub shut_down { + kill INT => $provider_pid, $consumer_pid; + close $provider; + close $consumer; +} + sub check_port { my ( $host, $port ) = @_;