CC: | Nicolas Rochelemagne <nicolas.rochelemagne [...] cpanel.net> |
Subject: | [PATCH] plack content is not always an array, it can be Plack::Util::Prototpye, for example in Plack::Middleware::AccessLog::Timed add one test with a Plack::Util::Prototype, factorize tests to easier add some more tests |
Date: | Tue, 20 Dec 2011 13:01:26 -0600 |
To: | bug-Plack-Middleware-ETag [...] rt.cpan.org |
From: | nicolas.rochelemagne [...] cpanel.net |
From: Nicolas Rochelemagne <nicolas.rochelemagne@cpanel.net>
---
lib/Plack/Middleware/ETag.pm | 3 +
t/01_basic.t | 248 +++++++++++++++++++++++-------------------
2 files changed, 140 insertions(+), 111 deletions(-)
diff --git a/lib/Plack/Middleware/ETag.pm b/lib/Plack/Middleware/ETag.pm
index f0a9dec..57eb4bd 100644
--- a/lib/Plack/Middleware/ETag.pm
+++ b/lib/Plack/Middleware/ETag.pm
@@ -52,6 +52,9 @@ sub call {
$etag .= ( sprintf "%x", $stats[7] );
}
} else {
+ # check that we have an array and not a Plack::Util::Prototpye
+ # ie : Plack::Middleware::AccessLog::Timed
+ return if ( ref [] ne ref $res->[2] );
my $sha = Digest::SHA->new;
$sha->add( @{ $res->[2] } );
$etag = $sha->hexdigest;
diff --git a/t/01_basic.t b/t/01_basic.t
index d1db7ba..d2f2981 100644
--- a/t/01_basic.t
+++ b/t/01_basic.t
@@ -9,121 +9,147 @@ use Plack::Builder;
use HTTP::Request::Common;
my $content = [qw/hello world/];
-my $sha = Digest::SHA->new->add(@$content)->hexdigest;
-
-my $handler = builder {
- enable "Plack::Middleware::ETag";
- sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
-};
-
-my $second_handler = builder {
- enable "Plack::Middleware::ETag";
- sub {
- [
- '200', [ 'Content-Type' => 'text/html', 'ETag' => '123' ],
- $content
- ];
+my $sha = Digest::SHA->new->add(@$content)->hexdigest;
+
+sub handler {
+ builder {
+ enable "Plack::Middleware::ETag";
+ sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
};
-};
-
-my $unmodified_handler = builder {
- enable "Plack::Middleware::ConditionalGET";
- enable "Plack::Middleware::ETag";
- sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
-};
-
-my $file_handler = builder {
- enable "Plack::Middleware::ETag";
- open my $fh, 'README';
- sub {[200, ['Content-Type' => 'text/html', ], $fh]};
-};
-
-my $cache_control = builder {
- enable "Plack::Middleware::ETag", cache_control => 1;
- sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
-};
-
-my $cache_control_array = builder {
- enable "Plack::Middleware::ETag",
- cache_control => [ 'must-revalidate', 'max-age=3600', 'no-store' ];
- sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
-};
-
-test_psgi
- app => $handler,
- client => sub {
- my $cb = shift;
- {
- my $req = GET "http://localhost/";
- my $res = $cb->($req);
- ok $res->header('ETag');
- is $res->header('ETag'), $sha;
- }
-};
-
-test_psgi
- app => $second_handler,
- client => sub {
- my $cb = shift;
- {
- my $req = GET "http://localhost/";
- my $res = $cb->($req);
- ok $res->header('ETag');
- is $res->header('ETag'), '123';
- }
-};
-
-test_psgi
- app => $unmodified_handler,
- client => sub {
- my $cb = shift;
+}
+
+sub second_handler {
+ builder {
+ enable "Plack::Middleware::ETag";
+ sub {
+ [
+ '200', [ 'Content-Type' => 'text/html', 'ETag' => '123' ],
+ $content
+ ];
+ };
+ };
+}
+
+sub unmodified_handler {
+ builder {
+ enable "Plack::Middleware::ConditionalGET";
+ enable "Plack::Middleware::ETag";
+ sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
+ };
+}
+
+sub file_handler {
+ builder {
+ enable "Plack::Middleware::ETag";
+ open my $fh, 'README';
+ sub { [ 200, [ 'Content-Type' => 'text/html', ], $fh ] };
+ };
+}
+
+sub cache_control {
+ builder {
+ enable "Plack::Middleware::ETag", cache_control => 1;
+ sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
+ };
+}
+
+sub cache_control_array {
+ builder {
+ enable "Plack::Middleware::ETag",
+ cache_control => [ 'must-revalidate', 'max-age=3600', 'no-store' ];
+ sub { [ '200', [ 'Content-Type' => 'text/html' ], $content ] };
+ };
+}
+
+# Plack::Middleware::AccessLog::Timed for example can return a plack answer with :
+# [ $status, $header, $timer_body = Plack::Util::inline_object ]
+my $inline_object = Plack::Util::inline_object(
+ getline => sub { },
+ close => sub { }
+);
+isa_ok( $inline_object, 'Plack::Util::Prototype' );
+ok( !Plack::Util::is_real_fh($inline_object) );
+
+sub invalid_handler {
+ builder {
+ enable "Plack::Middleware::ETag";
+ sub {
+ [
+ '200',
+ [ 'Content-Type' => 'text/html' ],
+ $inline_object || 'whatever'
+ ];
+ };
+ };
+}
+
+# declare apps to tests
+my @tests = (
+ { app => 'handler', headers => { ETag => $sha } },
+ { app => 'second_handler', headers => { ETag => 123 } },
{
- my $req = GET "http://localhost/", 'If-None-Match' => $sha;
- my $res = $cb->($req);
- ok $res->header('ETag');
- is $res->code, 304;
- ok !$res->content;
- }
-};
-
-test_psgi
- app => $file_handler,
- client => sub {
- my $cb = shift;
+ app => 'unmodified_handler',
+ request => [ 'If-None-Match' => $sha ],
+ headers => { ETag => $sha },
+ code => 304,
+ content => ''
+ },
+ { app => 'file_handler', headers => { ETag => '81a4-4ef0ae91-681' } }
+ , # code 200 + ok content
{
- my $req = GET "http://localhost/";
- my $res = $cb->($req);
- ok $res->header('ETag');
- is $res->code, 200;
- ok $res->content;
- }
-};
-
-test_psgi
- app => $cache_control,
- client => sub {
- my $cb = shift;
+ app => 'cache_control',
+ headers => { ETag => $sha, 'Cache-Control' => 'must-revalidate' }
+ },
{
- my $req = GET "http://localhost/";
- my $res = $cb->($req);
- ok $res->header('ETag');
- is $res->header('ETag'), $sha;
- is $res->header('Cache-Control'), 'must-revalidate';
- }
- };
-
-test_psgi
- app => $cache_control_array,
- client => sub {
- my $cb = shift;
+ app => 'cache_control_array',
+ headers => {
+ ETag => $sha,
+ 'Cache-Control' => 'must-revalidate, max-age=3600, no-store'
+ }
+ },
{
- my $req = GET "http://localhost/";
- my $res = $cb->($req);
- ok $res->header('ETag');
- is $res->header('ETag'), $sha;
- is $res->header('Cache-Control'),
- 'must-revalidate, max-age=3600, no-store';
- }
- };
+ app => 'invalid_handler',
+ headers => { ETag => undef },
+ content => undef
+ },
+
+);
+
+# test the apps
+
+foreach my $t (@tests) {
+ subtest "Testing app : $t->{app}" => sub {
+ no strict 'refs';
+ test_psgi
+ app => &{ $t->{app} },
+ client => sub {
+ my $cb = shift;
+ {
+
+ # launch the request
+ my @get = ("http://localhost/");
+ push( @get, @{ $t->{request} } ) if $t->{request};
+ my $req = GET @get;
+ my $res = $cb->($req);
+
+ # analyze headers
+ $t->{headers} ||= {};
+ foreach my $h ( keys %{ $t->{headers} } ) {
+ ok $res->header($h), "has header $h"
+ if defined $res->header($h);
+ is $res->header($h), $t->{headers}->{$h},
+ "header $h has expected value";
+ }
+
+ # analyze answer
+ is $res->code, $t->{code} || 200, "return code is ok";
+ ok $res->content, "content exists"
+ unless exists $t->{content} && ( !defined $t->{content} || $t->{content} eq '' );
+ is $res->content, $t->{content}, "content has expected value"
+ if exists $t->{content};
+ }
+ };
+ };
+}
done_testing;
--
1.7.7.1