diff options
Diffstat (limited to 'debian/perl-framework/t/modules/session.t')
-rw-r--r-- | debian/perl-framework/t/modules/session.t | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/debian/perl-framework/t/modules/session.t b/debian/perl-framework/t/modules/session.t new file mode 100644 index 0000000..91428fe --- /dev/null +++ b/debian/perl-framework/t/modules/session.t @@ -0,0 +1,208 @@ +use strict; +use warnings FATAL => 'all'; + +use Apache::Test; +use Apache::TestRequest; +use Apache::TestUtil; + +## +## mod_session tests +## + +# Code, session data, dirty, expiry, content. +my $checks_per_test = 5; + +# Session, API, Encoding, SessionEnv, SessionHeader, SessionMaxAge, +# SessionExpiryUpdateInterval, SessionInclude/Exclude. +my $num_tests = 2 + 4 + 5 + 2 + 1 + 4 + 7 + 3; + +my @todo = ( + # Session writable after decode failure - PR 58171 + 53, 54, + # Session writable after expired - PR 56052 + 88, 89 +); + +# Until the fix for PR 57300 is backported, sessions are always saved. +if (!have_min_apache_version('2.5')) { + my @todo_backport = ( 8, 18, 38, 43, 48, 58, 63, 133 ); + push(@todo, @todo_backport); +} + +plan tests => $num_tests * $checks_per_test, + todo => \@todo, + need need_module('session'), + need_min_apache_version('2.3.0'); + +# APR time is in microseconds. +use constant APR_TIME_PER_SEC => 1000000; + +# Don't use math ops, the result is too big for 32 Bit Perl +# Use adding of trailing "0"s instead +sub expiry_from_seconds +{ + my $seconds = shift; + return $seconds . "0" x (length(APR_TIME_PER_SEC) - 1); +} + +# check_result(name, res, session, dirty, expiry, response) +sub check_result +{ + my $name = shift; + my $res = shift; + my $session = shift // '(none)'; + my $dirty = shift // 0; + my $expiry = shift // 0; + my $response = shift // ''; + + ok t_cmp($res->code, 200, "response code ($name)"); + my $gotSession = $res->header('X-Test-Session') // '(none)'; + my $sessionData = $gotSession; + + if ($gotSession =~ /^(?:(.+)&)?expiry=([0-9]+)(?:&(.*))?$/i) { + # Don't use math ops, $2 is too big for 32 Bit Perl + # Use stripping of trailing "0"s instead + my $gotExpiry = substr($2, 0, -1 * (length(APR_TIME_PER_SEC) - 1)); + t_debug "expiry of $gotExpiry ($name)"; + ok $expiry && time() < $gotExpiry; + + # Combine the remaining data (if there is any) without the expiry. + $sessionData = join('&', grep(defined, ($1, $3))); + } + else { + t_debug "no expiry ($name)"; + ok !$expiry; + } + + ok t_cmp($sessionData, $session, "session header ($name)"); + my $got = $res->header('X-Test-Session-Dirty') // 0; + ok t_cmp($got, $dirty, "session dirty ($name)"); + $got = $res->content; + chomp($got); + ok t_cmp($got, $response, "body ($name)"); + return $gotSession; +} + +# check_get(name, path, session, dirty, expiry, response) +sub check_get +{ + my $name = shift; + my $path = shift; + + t_debug "$name: GET $path"; + my $res = GET "/sessiontest$path"; + return check_result $name, $res, @_; +} + +# check_post(name, path, data, session, dirty, expiry, response) +sub check_post +{ + my $name = shift; + my $path = shift; + my $data = shift; + + t_debug "$name: POST $path"; + my $res = POST "/sessiontest$path", content => $data; + return check_result $name, $res, @_; +} + +# check_custom(name, result, session, dirty, expiry, response) +sub check_custom +{ + my $name = shift; + my $res = shift; + + t_debug "$name"; + return check_result $name, $res, @_; +} + +my $session = 'test=value'; +my $encoded_prefix = 'TestEncoded:'; +my $encoded_session = $encoded_prefix . $session; +my $create_session = 'action=set&name=test&value=value'; +my $read_session = 'action=get&name=test'; + +# Session directive +check_post 'Cannot write session when off', '/', $create_session; +check_get 'New empty session is not saved', '/on'; + +# API optional functions +check_post 'Set session', '/on', $create_session, $session, 1; +check_post 'Get session', "/on?$session", $read_session, + undef, 0, 0, 'value'; +check_post 'Delete session', "/on?$session", 'action=set&name=test', '', 1; +check_post 'Edit session', "/on?$session", 'action=set&name=test&value=', + 'test=', 1; + +# Encoding hooks +check_post 'Encode session', '/on/encode', $create_session, + $encoded_session, 1; +check_post 'Decode session', "/on/encode?$encoded_session", $read_session, + undef, 0, 0, 'value'; +check_get 'Custom decoder failure', "/on/encode?$session"; +check_get 'Identity decoder failure', "/on?&=test"; +check_post 'Session writable after decode failure', "/on/encode?$session", + $create_session, $encoded_session, 1; + +# SessionEnv directive - requires mod_include +if (have_module('include')) { + check_custom 'SessionEnv Off', GET("/modules/session/env.shtml?$session"), + undef, 0, 0, '(none)'; + check_get 'SessionEnv On', "/on/env/on/env.shtml?$session", + undef, 0, 0, $session; +} +else { + for (1 .. 2 * $checks_per_test) { + skip "SessionEnv tests require mod_include", 1; + } +} + +# SessionHeader directive +check_custom 'SessionHeader', GET("/sessiontest/on?$session&another=1", + 'X-Test-Session-Override' => 'another=5&last=7'), + "$session&another=5&last=7", 1; + +# SessionMaxAge directive +my $future_expiry = expiry_from_seconds(time() + 200); + +check_get 'SessionMaxAge adds expiry', "/on/expire?$session", $session, 0, 1; +check_get 'Discard expired session', "/on/expire?$session&expiry=1", '', 0, 1; +check_get 'Keep non-expired session', + "/on/expire?$session&expiry=$future_expiry", $session, 0, 1; +check_post 'Session writable after expired', '/on/expire?expiry=1', + $create_session, $session, 1, 1; + +# SessionExpiryUpdateInterval directive - new in 2.5 +if (have_module('version') && have_min_apache_version('2.5')) { + my $max_expiry = expiry_from_seconds(time() + 100); + my $threshold_expiry = expiry_from_seconds(time() + 40); + + check_get 'SessionExpiryUpdateInterval off by default', + "/on/expire?$session&expiry=$max_expiry", $session, 0, 1; + check_get 'SessionExpiryUpdateInterval skips save', + "/on/expire/cache?$session&expiry=$max_expiry"; + check_post 'Session readable when save skipped', + "/on/expire/cache?$session&expiry=$max_expiry", $read_session, + undef, 0, 0, 'value'; + check_post 'Dirty overrides SessionExpiryUpdateInterval', + "/on/expire/cache?$session&expiry=$max_expiry", $create_session, + $session, 1, 1; + check_get 'Old session always updates expiry', + "/on/expire/cache?$session&expiry=$threshold_expiry", $session, 0, 1; + check_get 'New empty session with expiry not saved', "/on/expire/cache"; + check_post 'Can create session with SessionExpiryUpdateInterval', + "/on/expire/cache", $create_session, $session, 1, 1; +} +else { + for (1 .. 7 * $checks_per_test) { + skip "SessionExpiryUpdateInterval tests require backporting"; + } +} + +# SessionInclude/Exclude directives +check_post 'Cannot write session when not included', + "/on/include?$session", $create_session; +check_post 'Can read session when included', + "/on/include/yes?$session", $read_session, undef, 0, 0, 'value'; +check_post 'SessionExclude overrides SessionInclude', + "/on/include/yes/no?$session", $create_session; |