Permalink
Browse files

Item14061: Merge branch 'Item14061'

  • Loading branch information...
2 parents d82b6fe + e11b033 commit 6c215986751d597b8ca0e60a45e364cb8d9b7f90 @gac410 gac410 committed May 2, 2016
Showing with 298 additions and 10 deletions.
  1. +289 −6 UnitTestContrib/test/unit/CacheTests.pm
  2. +2 −2 core/lib/Foswiki.pm
  3. +7 −2 core/lib/Foswiki/PageCache.pm
@@ -59,7 +59,15 @@ sub fixture_groups {
}
}
- return ( \@page, [ 'view', 'rest' ], [ 'NoCompress', 'Compress' ] );
+ return (
+ \@page,
+ [ 'view', 'rest' ],
+ [ 'NoCompress', 'Compress' ],
+ [
+ 'refresh_all', 'refresh_cache', 'refresh_fire', 'refresh_on',
+ 'timing'
+ ],
+ );
}
sub dbcheckDBI {
@@ -250,12 +258,12 @@ sub check {
$this->assert( $one =~ s/\r//g, 'Failed to remove \r' );
$this->assert( $one =~ s/^(.*?)\n\n+//s, 'Failed to remove HTTP headers' );
my $one_head = $1;
- $this->assert( $one_head !~ /X-Foswiki-Pagecache/i, $one_head );
+ $this->assert_does_not_match( qr/X-Foswiki-Pagecache/i, $one_head );
$this->assert( $two =~ s/\r//g, 'Failed to remove \r' );
$this->assert( $two =~ s/^(.*?)\n\n+//s, 'Failed to remove HTTP headers' );
my $two_heads = $1;
- $this->assert( $two_heads =~ /^X-Foswiki-Pagecache: 1$/im, $two_heads );
+ $this->assert_matches( qr/X-Foswiki-Pagecache: 1/i, $two_heads );
print STDERR "To cache: "
. timestr( timediff( $p1end, $p1start ) ) . "\n";
@@ -292,14 +300,138 @@ s/<(span|div)([^>]*?)(\d+?)(show|hide|toggle)([^>]*?)>/'<'.$1.$2._mangleID($3).$
return;
}
+sub check_refresh {
+
+ my $this = shift;
+ my $pathinfo = shift;
+ my $refresh = shift;
+
+ my $user =
+ ( $refresh eq 'all' )
+ ? $Foswiki::cfg{AdminUserLogin}
+ : $this->{test_user_login};
+
+ $UI_FN ||= $this->getUIFn( $this->{uifn} );
+ $Foswiki::cfg{Cache}{Debug} = 1;
+ my $query = Unit::Request->new( { skin => ['none'], } );
+ $query->path_info($pathinfo);
+ $query->method('GET');
+
+ $this->createNewFoswikiSession( $user, $query, { $this->{uifn} => 1 } );
+
+ # This first request should *not* be satisfied from the cache, but
+ # the cache should be populated with the result.
+ my ( $one, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ }
+ );
+
+ $this->createNewFoswikiSession( $user, $query, { $this->{uifn} => 1 } );
+
+ # This second request should be satisfied from the cache
+ # How do we know it was?
+ ( my $two, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ }
+ );
+
+ $query = Unit::Request->new( { skin => ['none'], refresh => $refresh, } );
+ $query->path_info($pathinfo);
+ $query->method('GET');
+ $this->createNewFoswikiSession( $user, $query, { $this->{uifn} => 1 } );
+
+ # This third request with refresh should not be satisfied from the cache
+ # How do we know it was?
+ ( my $three, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ }
+ );
+ $this->assert( $one =~ s/\r//g, 'Failed to remove \r' );
+ $this->assert( $one =~ s/^(.*?)\n\n+//s, 'Failed to remove HTTP headers' );
+ my $one_head = $1;
+ $this->assert_does_not_match( qr/X-Foswiki-Pagecache/i, $one_head );
+
+ $this->assert( $two =~ s/\r//g, 'Failed to remove \r' );
+ $this->assert( $two =~ s/^(.*?)\n\n+//s, 'Failed to remove HTTP headers' );
+ my $two_heads = $1;
+ $this->assert_matches( qr/X-Foswiki-Pagecache: 1/i, $two_heads );
+
+ $this->assert( $three =~ s/\r//g, 'Failed to remove \r' );
+ $this->assert( $three =~ s/^(.*?)\n\n+//s,
+ 'Failed to remove HTTP headers' );
+ my $three_heads = $1;
+
+ if ($refresh) {
+ $this->assert_does_not_match( qr/X-Foswiki-Pagecache: 1/i,
+ $three_heads );
+ }
+ else {
+ $this->assert_matches( qr/X-Foswiki-Pagecache: 1/i, $three_heads );
+ }
+
+ return;
+}
+
+sub refresh_all {
+ my $this = shift;
+ $this->{refresh} = 'all';
+}
+
+sub refresh_on {
+ my $this = shift;
+ $this->{refresh} = 'on';
+}
+
+sub refresh_cache {
+ my $this = shift;
+ $this->{refresh} = 'cache';
+}
+
+sub refresh_fire {
+ my $this = shift;
+ $this->{refresh} = 'fire';
+}
+
+sub timing {
+ my $this = shift;
+ $this->{refresh} = undef;
+}
+
sub verify_simple {
my $this = shift;
- $this->check('/');
+
+ if ( $this->{refresh} ) {
+ $this->check_refresh( '/', $this->{refresh} );
+ }
+ else {
+ $this->check('/');
+ }
}
sub verify_topic {
my $this = shift;
- $this->check("/$Foswiki::cfg{SystemWebName}/FileAttribute");
+ if ( $this->{refresh} ) {
+ $this->check_refresh( "/$Foswiki::cfg{SystemWebName}/FileAttribute",
+ $this->{refresh} );
+ }
+ else {
+ $this->check("/$Foswiki::cfg{SystemWebName}/FileAttribute");
+ }
}
sub verify_utf8_topic {
@@ -312,7 +444,158 @@ sub verify_utf8_topic {
$meta->text($topic);
$meta->save();
- $this->check( Encode::encode_utf8("/$web/$topic") );
+ if ( $this->{refresh} ) {
+ $this->check_refresh( Encode::encode_utf8("/$web/$topic"),
+ $this->{refresh} );
+ }
+ else {
+ $this->check( Encode::encode_utf8("/$web/$topic") );
+ }
+}
+
+# Make sure that only admin users can issue refresh_all
+sub test_refresh_all {
+ my $this = shift;
+
+ SQLite(); # Initialized the cache
+ $Foswiki::cfg{Cache}{Enabled} = 1;
+
+ my $pathinfo = "/System/FileAttribute";
+
+ $UI_FN ||= $this->getUIFn("view");
+ $Foswiki::cfg{Cache}{Debug} = 1;
+
+ # First, make sure the topic is in the cache.
+
+ my $query = Unit::Request->new( { skin => ['none'] } );
+ $query->path_info($pathinfo);
+ $query->method('GET');
+
+ $this->createNewFoswikiSession( $this->{test_user_login},
+ $query, { view => 1 } );
+
+ my ( $junk, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ }
+ );
+
+ # Now attempt a refresh=all, from a non-admin user
+ # it should fail with an oops exception
+
+ $query = Unit::Request->new( { skin => ['none'], refresh => 'all', } );
+ $query->path_info($pathinfo);
+ $query->method('GET');
+
+ #$this->createNewFoswikiSession( $Foswiki::cfg{AdminUserLogin},
+ $this->createNewFoswikiSession( $this->{test_user_login},
+ $query, { view => 1 } );
+
+ ( my $one, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ try {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ $this->assert( 0, "refresh=all allowed by a non-admin user!" );
+ }
+ catch Foswiki::OopsException with {
+ my $e = shift;
+ $this->assert_str_equals( "cache_refresh", $e->{def},
+ $e->stringify() );
+ $this->assert_str_equals( "accessdenied", $e->{template},
+ $e->stringify() );
+ }
+ }
+ );
+
+ # Make sure that the page is still cached, that it wasn't removed
+ # during the oops processing
+
+ $query = Unit::Request->new( { skin => ['none'], } );
+ $query->path_info($pathinfo);
+ $query->method('GET');
+
+ $this->createNewFoswikiSession( $this->{test_user_login},
+ $query, { view => 1 } );
+
+ ( my $two, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ }
+ );
+
+ $this->assert( $two =~ s/\r//g, 'Failed to remove \r' );
+ $this->assert( $two =~ s/^(.*?)\n\n+//s, 'Failed to remove HTTP headers' );
+ my $two_heads = $1;
+ $this->assert_matches( qr/X-Foswiki-Pagecache: 1/i, $two_heads );
+
+ # Now refresh the cache as an admin
+
+ $query = Unit::Request->new( { skin => ['none'], refresh => 'all', } );
+ $query->path_info($pathinfo);
+ $query->method('GET');
+
+ $this->createNewFoswikiSession( $Foswiki::cfg{AdminUserLogin},
+ $query, { view => 1 } );
+
+ ( my $three, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ try {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ }
+ catch Foswiki::OopsException with {
+ my $e = shift;
+ $this->assert( 0, "Incorrect exception: " . $e->stringify() );
+ };
+
+ }
+ );
+
+ $this->assert( $three =~ s/\r//g, 'Failed to remove \r' );
+ $this->assert( $three =~ s/^(.*?)\n\n+//s,
+ 'Failed to remove HTTP headers' );
+ my $three_heads = $1;
+ $this->assert_does_not_match( qr/X-Foswiki-Pagecache: 1/i, $three_heads );
+
+ # Make sure that the page is not cached
+
+ $query = Unit::Request->new( { skin => ['none'], } );
+ $query->path_info($pathinfo);
+ $query->method('GET');
+
+ $this->createNewFoswikiSession( $this->{test_user_login},
+ $query, { view => 1 } );
+
+ ( my $four, $result, $stdout, $stderr ) = $this->capture(
+ sub {
+ no strict 'refs';
+ &{$UI_FN}( $this->{session} );
+ use strict 'refs';
+ $Foswiki::engine->finalize( $this->{session}{response},
+ $this->{session}{request} );
+ }
+ );
+
+ $this->assert( $four =~ s/\r//g, 'Failed to remove \r' );
+ $this->assert( $four =~ s/^(.*?)\n\n+//s, 'Failed to remove HTTP headers' );
+ my $four_heads = $1;
+ $this->assert_does_not_match( qr/X-Foswiki-Pagecache: 1/i, $four_heads );
+
}
1;
View
@@ -912,8 +912,6 @@ sub satisfiedByCache {
$hdrs->{'Content-Encoding'} = $encoding;
$hdrs->{'Vary'} = 'Accept-Encoding';
- # Mark the response so we know it was satisfied from the cache
- $hdrs->{'X-Foswiki-PageCache'} = 1;
}
else {
# e.g. CLI request satisfied from the cache, or old browser that doesn't
@@ -941,6 +939,8 @@ sub satisfiedByCache {
}
# set remaining headers
+ # Mark the response so we know it was satisfied from the cache
+ $hdrs->{'X-Foswiki-PageCache'} = 1;
$text = undef unless $this->setETags( $cachedPage, $hdrs );
$this->generateHTTPHeaders($hdrs);
@@ -222,8 +222,8 @@ sub cachePage {
my $refresh = $request->param('refresh') || '';
my $variationKey = $this->genVariationKey();
- # remove old entries
- if ( $session->inContext("isadmin") && $refresh =~ m/^(on|cache|all)$/ ) {
+ # remove old entries. Note refresh=all handled in getPage
+ if ( $refresh =~ m/^(on|cache)$/ ) {
$this->deletePage( $web, $topic ); # removes all variations
}
else {
@@ -316,6 +316,7 @@ sub getPage {
if ( $session->{users}->isAdmin( $session->{user} ) ) {
$this->deleteAll();
+ return undef;
}
else {
my $session = $Foswiki::Plugins::SESSION;
@@ -336,6 +337,10 @@ sub getPage {
$this->fireDependency( $web, $topic );
}
+ if ( $refresh =~ m/^(on|cache)$/ ) {
+ $this->deletePage( $web, $topic ); # removes all variations
+ }
+
# check cacheability
return undef unless $this->isCacheable( $web, $topic );

0 comments on commit 6c21598

Please sign in to comment.