Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions behat_suites.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ httpCache:
- Ibexa\Behat\Core\Context\ConfigurationContext
- Ibexa\Behat\API\Context\ContentContext
- Ibexa\Behat\API\Context\LanguageContext
- Ibexa\Behat\API\Context\RoleContext
setup-token:
paths:
- '%paths.base%/vendor/ibexa/http-cache/features/setup/invalidateToken.feature'
Expand Down
15 changes: 15 additions & 0 deletions features/setup/setup.feature
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,18 @@ Feature: Set system to desired state before tests
match:
Identifier\ContentType: [embeddedContentType]
"""

Scenario: Set up siteaccesses with distinct HTTP cache TTLs
# Dedicated siteaccesses so that TTL assertions do not depend on the default TTL,
# and so that shortening the TTL does not affect the timing of any other suite.
Given I add a siteaccess "cache_ttl_long" to "site_group" with settings
| key | value |
| content.default_ttl | 60 |
And I add a siteaccess "cache_ttl_short" to "site_group" with settings
| key | value |
| content.default_ttl | 5 |
# The Anonymous role's existing user/login policy is limited by SiteAccess, so without this
# the siteaccesses above are unreachable anonymously
And I add policies to "Anonymous"
| module | function |
| user | login |
17 changes: 17 additions & 0 deletions features/varnish/cacheKey.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Feature: As a site administrator I want equivalent requests to share one cache object

@varnish6 @varnish7
Scenario: Query string parameter order does not create a second cache object
# vcl_recv normalises the cache key with std.querysort, so the two requests below
# differ only in the order the parameters were written and must hit the same object
Given I create "Folder" Content items in root in "eng-GB"
| name | short_name |
| TestFolder | QsTestItem |
When I am on "/site/QsTestItem?b=2&a=1"
Then response headers contain
| Header | Value |
| x-cache | MISS |
When I am on "/site/QsTestItem?a=1&b=2"
Then response headers contain
| Header | Value |
| x-cache | HIT |
17 changes: 17 additions & 0 deletions features/varnish/tags.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Feature: As a site administrator I want responses to carry the cache tags Varnish invalidates on

@varnish6 @varnish7
Scenario: A Content view response is tagged with the content and location it was built from
# Tags are what every purge in this bundle keys on, but they are otherwise only tested
# indirectly - through whether a purge happened to work. fos_http_cache is configured
# with tag_mode: purgekeys, so TagHandler emits them space separated in an xkey header,
# always seeded with ez-all. The header only reaches clients inside the debuggers ACL.
Given I create "Folder" Content items in root in "eng-GB"
| name | short_name |
| TestFolder | TagTestItem |
When I visit "TagTestItem" on siteaccess "site"
Then response headers match pattern
| Header | Pattern |
| xkey | /(^\| )ez-all( \|$)/ |
| xkey | /(^\| )c\d+( \|$)/ |
| xkey | /(^\| )l\d+( \|$)/ |
107 changes: 107 additions & 0 deletions features/varnish/ttl.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
Feature: As a site administrator I want Varnish to apply the configured TTL and to serve stale content while it refreshes

# The siteaccesses used here are created by the setup suite and only differ in
# ibexa.system.<siteaccess>.content.default_ttl: cache_ttl_long is 60s, cache_ttl_short is 5s.
# Keeping them separate means the timing of the other suites is untouched and the assertions
# do not depend on whatever the default TTL happens to be.

@varnish6 @varnish7
Scenario: The TTL Varnish stores an object with comes from content.default_ttl
Given I create "Folder" Content items in root in "eng-GB"
| name | short_name |
| TestFolder | TtlTestItem |
When I visit "TtlTestItem" on siteaccess "cache_ttl_long"
And I reload the page
Then response headers contain
| Header | Value |
| x-cache | HIT |
And response headers match pattern
| Header | Pattern |
| x-cache-ttl | /^(5[0-9]\|60)\.\d+$/ |
When I visit "TtlTestItem" on siteaccess "cache_ttl_short"
And I reload the page
Then response headers contain
| Header | Value |
| x-cache | HIT |
And response headers match pattern
| Header | Pattern |
| x-cache-ttl | /^[0-4]\.\d+$/ |

@varnish6 @varnish7
Scenario: Responses for anonymous users may be cached by shared proxies for a short while
Given I create "Folder" Content items in root in "eng-GB"
| name | short_name |
| TestFolder | AnonCacheItem |
When I visit "AnonCacheItem" on siteaccess "cache_ttl_long"
Then response headers contain
| Header | Value |
| cache-control | public, s-maxage=600, stale-while-revalidate=300, stale-if-error=300 |
# The user context hash is an internal detail and must never be advertised to clients
And response headers match pattern
| Header | Pattern |
| vary | /^(?!.*X-User-Context-Hash).*$/i |

@varnish6 @varnish7
Scenario: Responses for logged-in users are not cacheable by shared proxies or browsers
Given I create "Folder" Content items in root in "eng-GB"
| name | short_name |
| TestFolder | AdminCacheItem |
And I am viewing the pages on siteaccess "cache_ttl_long" as "admin" with password "publish"
When I visit "AdminCacheItem" on siteaccess "cache_ttl_long"
Then response headers contain
| Header | Value |
| cache-control | private, no-cache, no-store, must-revalidate |

@varnish6 @varnish7
Scenario: An expired object is served from grace and refreshed in the background
Given I create "Folder" Content items in root in "eng-GB"
| name | short_name |
| TestFolder | StaleTestItem |
And I visit "StaleTestItem" on siteaccess "cache_ttl_short"
And I reload the page
And response headers contain
| Header | Value |
| x-cache | HIT |
When I wait 7 seconds
And I reload the page
# A negative obj.ttl proves the object is past its TTL and delivered from the grace window
Then response headers contain
| Header | Value |
| x-cache | HIT |
And response headers match pattern
| Header | Pattern |
| x-cache-ttl | /^-\d/ |
# The stale hit triggered a background fetch; the first request to the object it
# inserted reports MISS, the one after that is a hit on a fresh object again
When I wait 2 seconds
And I reload the page
And I reload the page
Then response headers contain
| Header | Value |
| x-cache | HIT |
And response headers match pattern
| Header | Pattern |
| x-cache-ttl | /^[0-4]\.\d+$/ |

@varnish6
Scenario: A logged-in user in the grace window gets a refreshed response, not a stale one
# varnish6.vcl vcl_hit: when the request carries a session cookie and the object is in
# grace, it does return (miss) so that editors are never shown stale content.
# varnish7.vcl has no vcl_hit at all and cannot be given the same one, because
# return (miss) was removed from that subroutine in Varnish 7 - so Varnish 7 and later
# deliver the stale object here instead. Tracked as a separate ticket; once varnish7.vcl
# gains the equivalent (return (pass)), this scenario can be tagged @varnish7 as well.
Given I create "Folder" Content items in root in "eng-GB"
| name | short_name |
| TestFolder | StaleAdminTestItem |
And I am viewing the pages on siteaccess "cache_ttl_short" as "admin" with password "publish"
And I visit "StaleAdminTestItem" on siteaccess "cache_ttl_short"
And I reload the page
And response headers contain
| Header | Value |
| x-cache | HIT |
When I wait 7 seconds
And I reload the page
Then response headers contain
| Header | Value |
| x-cache | MISS |