function ResourceObjectNormalizerCacherTest::testMaxAgeCorrection

Same name and namespace in other branches
  1. 11.x core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php \Drupal\Tests\jsonapi\Kernel\EventSubscriber\ResourceObjectNormalizerCacherTest::testMaxAgeCorrection()

Tests that normalization max-age is correct.

When max-age for a cached record is set the expiry is set accordingly. But if the cached normalization is partially used in a later normalization the max-age should be adjusted to a new timestamp.

If we don't do this the expires of the cache record will be reset based on the original max age. This leads to a drift in the expiry time of the record.

If a field tells the cache it should expire in exactly 1 hour, then if the cached data is used 10 minutes later in another resource, that cache should expire in 50 minutes and not reset to 60 minutes.

File

core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php, line 130

Class

ResourceObjectNormalizerCacherTest
@coversDefaultClass \Drupal\jsonapi\EventSubscriber\ResourceObjectNormalizationCacher[[api-linebreak]] @group jsonapi

Namespace

Drupal\Tests\jsonapi\Kernel\EventSubscriber

Code

public function testMaxAgeCorrection() : void {
  $this->installEntitySchema('entity_test_computed_field');
  // Use EntityTestComputedField since ComputedTestCacheableStringItemList has a max age of 800
  $baseMaxAge = 800;
  $entity = EntityTestComputedField::create([]);
  $entity->save();
  $resource_type = $this->resourceTypeRepository
    ->get($entity->getEntityTypeId(), $entity->bundle());
  $resource_object = ResourceObject::createFromEntity($resource_type, $entity);
  $resource_normalization = $this->serializer
    ->normalize($resource_object, 'api_json', [
    'account' => NULL,
  ]);
  $this->assertEquals($baseMaxAge, $resource_normalization->getCacheMaxAge());
  // Save the normalization to cache, this is done at TerminateEvent.
  $http_kernel = $this->prophesize(HttpKernelInterface::class);
  $request = $this->prophesize(Request::class);
  $response = $this->prophesize(Response::class);
  $event = new TerminateEvent($http_kernel->reveal(), $request->reveal(), $response->reveal());
  $this->cacher
    ->onTerminate($event);
  // Change request time to 500 seconds later
  $current_request = \Drupal::requestStack()->getCurrentRequest();
  $current_request->server
    ->set('REQUEST_TIME', $current_request->server
    ->get('REQUEST_TIME') + 500);
  $resource_normalization = $this->serializer
    ->normalize($resource_object, 'api_json', [
    'account' => NULL,
  ]);
  $this->assertEquals($baseMaxAge - 500, $resource_normalization->getCacheMaxAge(), 'Max age should be 300 since 500 seconds has passed');
  // Change request time to 800 seconds later, this is the last second the
  // cache backend would return cached data. The max-age at that time should
  // be 0 which is the same as the expire time of the cache entry.
  $current_request->server
    ->set('REQUEST_TIME', $current_request->server
    ->get('REQUEST_TIME') + 800);
  $resource_normalization = $this->serializer
    ->normalize($resource_object, 'api_json', [
    'account' => NULL,
  ]);
  $this->assertEquals(0, $resource_normalization->getCacheMaxAge(), 'Max age should be 0 since max-age has passed');
  // Change request time to 801 seconds later. This validates that max-age
  // never becomes negative. This should never happen as the cache entry
  // is expired at this time and the cache backend would not return data.
  $current_request->server
    ->set('REQUEST_TIME', $current_request->server
    ->get('REQUEST_TIME') + 801);
  $resource_normalization = $this->serializer
    ->normalize($resource_object, 'api_json', [
    'account' => NULL,
  ]);
  $this->assertEquals(0, $resource_normalization->getCacheMaxAge(), 'Max age should be 0 since max-age has passed a second ago');
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.