Quantcast
Channel: Issues for Drupal core
Viewing all articles
Browse latest Browse all 298755

Harden test EntityResource + Dynamic Page Cache test coverage

$
0
0

Problem/Motivation

Reported by @effulgentsia at #2827797-55: ResourceResponse(Subscriber) + Dynamic Page Cache: making authenticated ResourceResponses significantly faster:

+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -395,13 +409,44 @@ public function testGet() {
+        // Assert that Dynamic Page Cache did not store a ResourceResponse object,
+        // which needs serialization after every cache hit. Instead, it should
+        // contain a flattened response. Otherwise performance suffers.
+        // @see \Drupal\rest\EventSubscriber\ResourceResponseSubscriber::flattenResponse()
+        $cache_items = $this->container->get('database')
+          ->query("SELECT cid, data FROM {cache_dynamic_page_cache} WHERE cid LIKE :pattern", [
+            ':pattern' => '%[route]=rest.%',
+          ])
+          ->fetchAllAssoc('cid');
+        foreach ($cache_items as $cid => $cache_item) {

This test seems a little brittle. If the cid pattern changes in the future, this test will return an empty array and the foreach will get silently skipped, so the test will still pass. Perhaps there should be a followup to improve on this? Do we really have a situation where we don't know the exact $cid to check for?

We need the wildcard, to fetch the multiple relevant cache items: there's a cache redirect cache item, and an "actual" cache item.

If I add:

 .../tests/src/Functional/EntityResource/EntityResourceTestBase.php | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index 5bcf5fe..04a66f6 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -437,6 +437,7 @@ public function testGet() {
           ->fetchAllAssoc('cid');
         foreach ($cache_items as $cid => $cache_item) {
           $cached_data = unserialize($cache_item->data);
+          var_dump($cached_data);
           if (!isset($cached_data['#cache_redirect'])) {
             $cached_response = $cached_data['#response'];
             $this->assertNotInstanceOf(ResourceResponseInterface::class, $cached_response);

And then run NodeJsonBasicAuthTest, you get this output:

array(2) {
  ["#cache_redirect"]=>
  bool(true)
  ["#cache"]=>
  array(5) {
    ["keys"]=>
    array(1) {
      [0]=>
      string(8) "response"
    }
    ["contexts"]=>
    array(4) {
      [0]=>
      string(14) "request_format"
      [1]=>
      string(5) "route"
      [2]=>
      string(8) "url.site"
      [3]=>
      string(16) "user.permissions"
    }
    ["tags"]=>
    array(2) {
      [0]=>
      string(32) "config:rest.resource.entity.node"
      [1]=>
      string(6) "node:1"
    }
    ["max-age"]=>
    int(-1)
    ["bin"]=>
    string(18) "dynamic_page_cache"
  }
}
array(5) {
  ["#markup"]=>
  string(0) ""
  ["#attached"]=>
  string(0) ""
  ["#cache"]=>
  array(3) {
    ["contexts"]=>
    array(4) {
      [0]=>
      string(14) "request_format"
      [1]=>
      string(5) "route"
      [2]=>
      string(8) "url.site"
      [3]=>
      string(16) "user.permissions"
    }
    ["tags"]=>
    array(2) {
      [0]=>
      string(32) "config:rest.resource.entity.node"
      [1]=>
      string(6) "node:1"
    }
    ["max-age"]=>
    int(-1)
  }
  ["#cache_properties"]=>
  array(1) {
    [0]=>
    string(9) "#response"
  }
  ["#response"]=>
  object(Drupal\Core\Cache\CacheableResponse)#11508 (7) {
    ["headers"]=>
    object(Symfony\Component\HttpFoundation\ResponseHeaderBag)#1223 (5) {
      ["computedCacheControl":protected]=>
      array(2) {
        ["no-cache"]=>
        bool(true)
        ["private"]=>
        bool(true)
      }
      ["cookies":protected]=>
      array(0) {
      }
      ["headerNames":protected]=>
      array(3) {
        ["cache-control"]=>
        string(13) "Cache-Control"
        ["link"]=>
        string(4) "Link"
        ["content-type"]=>
        string(12) "Content-Type"
      }
      ["headers":protected]=>
      array(3) {
        ["cache-control"]=>
        array(1) {
          [0]=>
          string(17) "no-cache, private"
        }
        ["link"]=>
        array(5) {
          [0]=>
          string(35) "<http://d8/node/1>; rel="canonical""
          [1]=>
          string(78) "<http://d8/node/1/delete>; rel="https://drupal.org/link-relations/delete-form""
          [2]=>
          string(40) "<http://d8/node/1/edit>; rel="edit-form""
          [3]=>
          string(51) "<http://d8/node/1/revisions>; rel="version-history""
          [4]=>
          string(68) "<http://d8/node/1>; rel="https://drupal.org/link-relations/revision""
        }
        ["content-type"]=>
        array(1) {
          [0]=>
          string(16) "application/json"
        }
      }
      ["cacheControl":protected]=>
      array(0) {
      }
    }
    ["content":protected]=>
    string(800) "{"nid":[{"value":1}],"uuid":[{"value":"7e0ce3b9-082e-45e6-8ede-489ab77277d8"}],"vid":[{"value":1}],"langcode":[{"value":"en"}],"type":[{"target_id":"camelids","target_type":"node_type","target_uuid":"a4050c00-df34-4d74-92f4-6e08e73c8dfb"}],"revision_timestamp":[{"value":123456789}],"revision_uid":[{"target_id":2,"target_type":"user","target_uuid":"068851de-a726-4984-9d42-8578bd427ac2","url":"\/user\/2"}],"revision_log":[],"status":[{"value":true}],"title":[{"value":"Llama"}],"uid":[{"target_id":2,"target_type":"user","target_uuid":"068851de-a726-4984-9d42-8578bd427ac2","url":"\/user\/2"}],"created":[{"value":123456789}],"changed":[{"value":1494525772}],"promote":[{"value":true}],"sticky":[{"value":false}],"revision_translation_affected":[{"value":true}],"default_langcode":[{"value":true}]}"
    ["version":protected]=>
    string(3) "1.0"
    ["statusCode":protected]=>
    int(200)
    ["statusText":protected]=>
    string(2) "OK"
    ["charset":protected]=>
    NULL
    ["cacheabilityMetadata":protected]=>
    object(Drupal\Core\Cache\CacheableMetadata)#7539 (3) {
      ["cacheContexts":protected]=>
      array(2) {
        [0]=>
        string(8) "url.site"
        [1]=>
        string(16) "user.permissions"
      }
      ["cacheTags":protected]=>
      array(2) {
        [0]=>
        string(32) "config:rest.resource.entity.node"
        [1]=>
        string(6) "node:1"
      }
      ["cacheMaxAge":protected]=>
      int(-1)
    }
  }
}

Proposed resolution

Because there's always a cache redirect, assert the number of cache items.

Remaining tasks

User interface changes

None.

API changes

None.

Data model changes

None.


Viewing all articles
Browse latest Browse all 298755

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>