From 6951f4d77a73b7b2a7e4bb6201e9ed65e4dc7e50 Mon Sep 17 00:00:00 2001 From: catch Date: Fri, 27 Aug 2021 12:36:31 +0100 Subject: [PATCH] Issue #3225328 by mxr576, Berdir, longwave: Improve page performance by sorting cache contexts/tags on-demand --- core/lib/Drupal/Core/Cache/Cache.php | 4 +- .../Core/Cache/Context/ContextCacheKeys.php | 5 +++ .../FinishResponseSubscriber.php | 8 +++- .../tests/src/Kernel/BlockViewBuilderTest.php | 10 ++--- .../CommentDefaultFormatterCacheTagsTest.php | 6 +-- .../Kernel/ContentModerationAccessTest.php | 8 ++-- .../filter/tests/src/Kernel/FilterAPITest.php | 4 +- .../ForumListingBreadcrumbBuilderTest.php | 10 ++--- .../ForumNodeBreadcrumbBuilderTest.php | 8 ++-- .../tests/src/Functional/ResourceTestBase.php | 6 +-- .../Kernel/Controller/EntityResourceTest.php | 2 +- .../JsonApiDocumentTopLevelNormalizerTest.php | 4 +- .../Unit/BlockComponentRenderArrayTest.php | 8 ++-- .../tests/src/Kernel/MediaEmbedFilterTest.php | 12 +++--- .../MediaEmbedFilterTranslationTest.php | 2 +- .../src/Kernel/MediaLibraryAccessTest.php | 4 +- ...enuLinkContentCacheabilityBubblingTest.php | 4 +- .../tests/src/Kernel/NodeListBuilderTest.php | 2 +- .../EntityResource/EntityResourceTestBase.php | 2 +- .../tests/src/Functional/ResourceTestBase.php | 4 +- .../Rest/EntityTestTextItemNormalizerTest.php | 2 +- .../Entity/EntityCacheTagsTestBase.php | 4 +- .../Entity/EntityListBuilderTest.php | 2 +- .../src/Functional/Routing/RouterTest.php | 12 +++++- .../tests/src/Kernel/Common/UrlTest.php | 2 +- .../PathBasedBreadcrumbBuilderTest.php | 28 ++++++------- .../tests/src/Unit/Menu/MenuLinkTreeTest.php | 1 - core/modules/views/src/Entity/View.php | 2 + .../src/Tests/AssertViewsCacheTagsTrait.php | 12 +++--- .../Handler/FieldRenderedEntityTest.php | 4 +- .../src/Kernel/RenderCacheIntegrationTest.php | 2 +- .../tests/src/Unit/Plugin/query/SqlTest.php | 2 +- .../Tests/Core/Access/AccessResultTest.php | 10 ++--- .../Drupal/Tests/Core/Cache/CacheTest.php | 12 +++--- .../Core/Cache/CacheableMetadataTest.php | 16 ++++---- .../Tests/Core/Entity/EntityUnitTest.php | 40 ++++++++++--------- .../Tests/Core/Menu/LocalTaskManagerTest.php | 6 +-- .../Core/Render/BubbleableMetadataTest.php | 8 ++-- .../Core/Render/RendererBubblingTest.php | 33 ++++++++------- .../Drupal/Tests/Core/Render/RendererTest.php | 2 +- .../Tests/Core/Render/RendererTestBase.php | 14 ++++++- 41 files changed, 176 insertions(+), 151 deletions(-) diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php index 8f8e97e8668..da380995950 100644 --- a/core/lib/Drupal/Core/Cache/Cache.php +++ b/core/lib/Drupal/Core/Cache/Cache.php @@ -28,8 +28,7 @@ class Cache { */ public static function mergeContexts(array ...$cache_contexts) { $cache_contexts = array_unique(array_merge(...$cache_contexts)); - assert(\Drupal::service('cache_contexts_manager')->assertValidTokens($cache_contexts)); - sort($cache_contexts); + assert(\Drupal::service('cache_contexts_manager')->assertValidTokens($cache_contexts), sprintf('Failed to assert that "%s" are valid cache contexts.', implode(', ', $cache_contexts))); return $cache_contexts; } @@ -53,7 +52,6 @@ class Cache { public static function mergeTags(array ...$cache_tags) { $cache_tags = array_unique(array_merge(...$cache_tags)); assert(Inspector::assertAllStrings($cache_tags), 'Cache tags must be valid strings'); - sort($cache_tags); return $cache_tags; } diff --git a/core/lib/Drupal/Core/Cache/Context/ContextCacheKeys.php b/core/lib/Drupal/Core/Cache/Context/ContextCacheKeys.php index 27b227cb603..d2f01ae0705 100644 --- a/core/lib/Drupal/Core/Cache/Context/ContextCacheKeys.php +++ b/core/lib/Drupal/Core/Cache/Context/ContextCacheKeys.php @@ -23,6 +23,11 @@ class ContextCacheKeys extends CacheableMetadata { * The cache context keys. */ public function __construct(array $keys) { + // Domain invariant: cache keys must be always sorted. + // Sorting keys warrants that different combination of the same keys + // generates the same cache cid. + // @see \Drupal\Core\Render\RenderCache::createCacheID() + sort($keys); $this->keys = $keys; } diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php index 0a915ce6947..d00270f793a 100644 --- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php @@ -159,8 +159,12 @@ class FinishResponseSubscriber implements EventSubscriberInterface { // Expose the cache contexts and cache tags associated with this page in a // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively. $response_cacheability = $response->getCacheableMetadata(); - $response->headers->set('X-Drupal-Cache-Tags', implode(' ', $response_cacheability->getCacheTags())); - $response->headers->set('X-Drupal-Cache-Contexts', implode(' ', $this->cacheContextsManager->optimizeTokens($response_cacheability->getCacheContexts()))); + $cache_tags = $response_cacheability->getCacheTags(); + sort($cache_tags); + $response->headers->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags)); + $cache_contexts = $this->cacheContextsManager->optimizeTokens($response_cacheability->getCacheContexts()); + sort($cache_contexts); + $response->headers->set('X-Drupal-Cache-Contexts', implode(' ', $cache_contexts)); $max_age_message = $response_cacheability->getCacheMaxAge(); if ($max_age_message === 0) { $max_age_message = '0 (Uncacheable)'; diff --git a/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php b/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php index 3a694f4ca2e..df7fba45a3a 100644 --- a/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php +++ b/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php @@ -296,8 +296,8 @@ class BlockViewBuilderTest extends KernelTestBase { // - the built render array; $build = $this->getBlockRenderArray(); $this->assertSame($expected_keys, $build['#cache']['keys']); - $this->assertSame($expected_contexts, $build['#cache']['contexts']); - $this->assertSame($expected_tags, $build['#cache']['tags']); + $this->assertEqualsCanonicalizing($expected_contexts, $build['#cache']['contexts']); + $this->assertEqualsCanonicalizing($expected_tags, $build['#cache']['tags']); $this->assertSame($expected_max_age, $build['#cache']['max-age']); $this->assertFalse(isset($build['#create_placeholder'])); // - the rendered render array; @@ -307,9 +307,9 @@ class BlockViewBuilderTest extends KernelTestBase { $cid = implode(':', $expected_keys) . ':' . implode(':', \Drupal::service('cache_contexts_manager')->convertTokensToKeys($final_cache_contexts)->getKeys()); $cache_item = $this->container->get('cache.render')->get($cid); $this->assertNotEmpty($cache_item, 'The block render element has been cached with the expected cache ID.'); - $this->assertSame(Cache::mergeTags($expected_tags, ['rendered']), $cache_item->tags); - $this->assertSame($final_cache_contexts, $cache_item->data['#cache']['contexts']); - $this->assertSame($expected_tags, $cache_item->data['#cache']['tags']); + $this->assertEqualsCanonicalizing(Cache::mergeTags($expected_tags, ['rendered']), $cache_item->tags); + $this->assertEqualsCanonicalizing($final_cache_contexts, $cache_item->data['#cache']['contexts']); + $this->assertEqualsCanonicalizing($expected_tags, $cache_item->data['#cache']['tags']); $this->assertSame($expected_max_age, $cache_item->data['#cache']['max-age']); $this->container->get('cache.render')->delete($cid); diff --git a/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php b/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php index f96c196d421..1997a843bbf 100644 --- a/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php +++ b/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php @@ -92,8 +92,7 @@ class CommentDefaultFormatterCacheTagsTest extends EntityKernelTestBase { 'config:field.storage.comment.comment_body', 'config:user.settings', ]; - sort($expected_cache_tags); - $this->assertEquals($expected_cache_tags, $build['#cache']['tags']); + $this->assertEqualsCanonicalizing($expected_cache_tags, $build['#cache']['tags']); // Create a comment on that entity. Comment loading requires that the uid // also exists in the {users} table. @@ -140,8 +139,7 @@ class CommentDefaultFormatterCacheTagsTest extends EntityKernelTestBase { 'config:field.storage.comment.comment_body', 'config:user.settings', ]; - sort($expected_cache_tags); - $this->assertEquals($expected_cache_tags, $build['#cache']['tags']); + $this->assertEqualsCanonicalizing($expected_cache_tags, $build['#cache']['tags']); // Build a render array with the entity in a sub-element so that lazy // builder elements bubble up outside of the entity and we can check that diff --git a/core/modules/content_moderation/tests/src/Kernel/ContentModerationAccessTest.php b/core/modules/content_moderation/tests/src/Kernel/ContentModerationAccessTest.php index 52c899fb440..84ef7247440 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ContentModerationAccessTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationAccessTest.php @@ -79,8 +79,8 @@ class ContentModerationAccessTest extends KernelTestBase { $result = $node->access('update', $account, TRUE); $this->assertFalse($result->isAllowed()); - $this->assertEquals(['user.permissions'], $result->getCacheContexts()); - $this->assertEquals(['config:workflows.workflow.editorial', 'node:' . $node->id()], $result->getCacheTags()); + $this->assertEqualsCanonicalizing(['user.permissions'], $result->getCacheContexts()); + $this->assertEqualsCanonicalizing(['config:workflows.workflow.editorial', 'node:' . $node->id()], $result->getCacheTags()); $this->assertEquals(CacheBackendInterface::CACHE_PERMANENT, $result->getCacheMaxAge()); $authenticated->grantPermission('use editorial transition create_new_draft'); @@ -89,8 +89,8 @@ class ContentModerationAccessTest extends KernelTestBase { \Drupal::entityTypeManager()->getAccessControlHandler('node')->resetCache(); $result = $node->access('update', $account, TRUE); $this->assertTrue($result->isAllowed()); - $this->assertEquals(['user.permissions'], $result->getCacheContexts()); - $this->assertEquals(['config:workflows.workflow.editorial', 'node:' . $node->id()], $result->getCacheTags()); + $this->assertEqualsCanonicalizing(['user.permissions'], $result->getCacheContexts()); + $this->assertEqualsCanonicalizing(['config:workflows.workflow.editorial', 'node:' . $node->id()], $result->getCacheTags()); $this->assertEquals(CacheBackendInterface::CACHE_PERMANENT, $result->getCacheMaxAge()); } diff --git a/core/modules/filter/tests/src/Kernel/FilterAPITest.php b/core/modules/filter/tests/src/Kernel/FilterAPITest.php index cedef4e0903..76255f6f7eb 100644 --- a/core/modules/filter/tests/src/Kernel/FilterAPITest.php +++ b/core/modules/filter/tests/src/Kernel/FilterAPITest.php @@ -298,7 +298,7 @@ class FilterAPITest extends EntityKernelTestBase { // The cache tags set by the filter_test_cache_merge filter. 'merge:tag', ]; - $this->assertEquals($expected_cache_tags, $build['#cache']['tags'], 'Expected cache tags present.'); + $this->assertEqualsCanonicalizing($expected_cache_tags, $build['#cache']['tags'], 'Expected cache tags present.'); $expected_cache_contexts = [ // The cache context set by the filter_test_cache_contexts filter. 'languages:' . LanguageInterface::TYPE_CONTENT, @@ -308,7 +308,7 @@ class FilterAPITest extends EntityKernelTestBase { // The cache tags set by the filter_test_cache_merge filter. 'user.permissions', ]; - $this->assertEquals($expected_cache_contexts, $build['#cache']['contexts'], 'Expected cache contexts present.'); + $this->assertEqualsCanonicalizing($expected_cache_contexts, $build['#cache']['contexts'], 'Expected cache contexts present.'); $expected_markup = '

Hello, world!

This is a dynamic llama.

'; $this->assertEquals($expected_markup, $build['#markup'], 'Expected #lazy_builder callback has been applied.'); } diff --git a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php index 39351231c5a..442fd104dc8 100644 --- a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php +++ b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumListingBreadcrumbBuilderTest.php @@ -214,9 +214,9 @@ class ForumListingBreadcrumbBuilderTest extends UnitTestCase { ]; $breadcrumb = $breadcrumb_builder->build($route_match); $this->assertEquals($expected1, $breadcrumb->getLinks()); - $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); - $this->assertEquals(['taxonomy_term:1', 'taxonomy_term:23', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); - $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); + $this->assertEqualsCanonicalizing(['route'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing(['taxonomy_term:1', 'taxonomy_term:23', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); // Second test. $expected2 = [ @@ -227,8 +227,8 @@ class ForumListingBreadcrumbBuilderTest extends UnitTestCase { ]; $breadcrumb = $breadcrumb_builder->build($route_match); $this->assertEquals($expected2, $breadcrumb->getLinks()); - $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); - $this->assertEquals(['taxonomy_term:1', 'taxonomy_term:2', 'taxonomy_term:23', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['route'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing(['taxonomy_term:1', 'taxonomy_term:2', 'taxonomy_term:23', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } diff --git a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php index 1c37a806dff..a5aa6c5e0b6 100644 --- a/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php +++ b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php @@ -221,8 +221,8 @@ class ForumNodeBreadcrumbBuilderTest extends UnitTestCase { ]; $breadcrumb = $breadcrumb_builder->build($route_match); $this->assertEquals($expected1, $breadcrumb->getLinks()); - $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); - $this->assertEquals(['taxonomy_term:1', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['route'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing(['taxonomy_term:1', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); // Second test. @@ -234,8 +234,8 @@ class ForumNodeBreadcrumbBuilderTest extends UnitTestCase { ]; $breadcrumb = $breadcrumb_builder->build($route_match); $this->assertEquals($expected2, $breadcrumb->getLinks()); - $this->assertEquals(['route'], $breadcrumb->getCacheContexts()); - $this->assertEquals(['taxonomy_term:1', 'taxonomy_term:2', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['route'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing(['taxonomy_term:1', 'taxonomy_term:2', 'taxonomy_vocabulary:5'], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } diff --git a/core/modules/jsonapi/tests/src/Functional/ResourceTestBase.php b/core/modules/jsonapi/tests/src/Functional/ResourceTestBase.php index 17f4e2b809a..d7dae50d0c1 100644 --- a/core/modules/jsonapi/tests/src/Functional/ResourceTestBase.php +++ b/core/modules/jsonapi/tests/src/Functional/ResourceTestBase.php @@ -722,14 +722,14 @@ abstract class ResourceTestBase extends BrowserTestBase { // Expected cache tags: X-Drupal-Cache-Tags header. $this->assertSame($expected_cache_tags !== FALSE, $response->hasHeader('X-Drupal-Cache-Tags')); if (is_array($expected_cache_tags)) { - $this->assertSame($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0])); + $this->assertEqualsCanonicalizing($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0])); } // Expected cache contexts: X-Drupal-Cache-Contexts header. $this->assertSame($expected_cache_contexts !== FALSE, $response->hasHeader('X-Drupal-Cache-Contexts')); if (is_array($expected_cache_contexts)) { $optimized_expected_cache_contexts = \Drupal::service('cache_contexts_manager')->optimizeTokens($expected_cache_contexts); - $this->assertSame($optimized_expected_cache_contexts, explode(' ', $response->getHeader('X-Drupal-Cache-Contexts')[0])); + $this->assertEqualsCanonicalizing($optimized_expected_cache_contexts, explode(' ', $response->getHeader('X-Drupal-Cache-Contexts')[0])); } // Expected Page Cache header value: X-Drupal-Cache header. @@ -788,7 +788,7 @@ abstract class ResourceTestBase extends BrowserTestBase { } foreach ($expected_document as $member_name => $expected_member) { $actual_member = $actual_document[$member_name]; - $this->assertEquals($expected_member, $actual_member, "The '$member_name' member was not as expected."); + $this->assertEqualsCanonicalizing($expected_member, $actual_member, "The '$member_name' member was not as expected."); } } diff --git a/core/modules/jsonapi/tests/src/Kernel/Controller/EntityResourceTest.php b/core/modules/jsonapi/tests/src/Kernel/Controller/EntityResourceTest.php index 5f0246f2cbc..bbe21b9e225 100644 --- a/core/modules/jsonapi/tests/src/Kernel/Controller/EntityResourceTest.php +++ b/core/modules/jsonapi/tests/src/Kernel/Controller/EntityResourceTest.php @@ -207,7 +207,7 @@ class EntityResourceTest extends JsonapiKernelTestBase { $data = $response->getResponseData()->getData(); $this->assertCount(1, $data); $this->assertEquals($this->node2->uuid(), $data->toArray()[0]->getId()); - $this->assertEquals(['node:2', 'node_list'], $response->getCacheableMetadata()->getCacheTags()); + $this->assertEqualsCanonicalizing(['node:2', 'node_list'], $response->getCacheableMetadata()->getCacheTags()); } /** diff --git a/core/modules/jsonapi/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php b/core/modules/jsonapi/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php index ef814cf70f6..f2dd059271a 100644 --- a/core/modules/jsonapi/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php +++ b/core/modules/jsonapi/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php @@ -310,7 +310,7 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase { $this->assertTrue(!isset($normalized['included'][1]['attributes']['created'])); // Make sure that the cache tags for the includes and the requested entities // are bubbling as expected. - $this->assertSame( + $this->assertEqualsCanonicalizing( ['file:1', 'node:1', 'taxonomy_term:1', 'taxonomy_term:2', 'user:1'], $jsonapi_doc_object->getCacheTags() ); @@ -400,7 +400,7 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase { $this->assertCount(12, $normalized['included'][1]['attributes']); // Make sure that the cache tags for the includes and the requested entities // are bubbling as expected. - $this->assertSame( + $this->assertEqualsCanonicalizing( ['node:1', 'taxonomy_term:1', 'taxonomy_term:2', 'user:1'], $jsonapi_doc_object->getCacheTags() ); diff --git a/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php b/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php index cbd92bf2795..76281f87316 100644 --- a/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php +++ b/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php @@ -122,7 +122,7 @@ class BlockComponentRenderArrayTest extends UnitTestCase { 'content' => $block_content, ]; - $expected_cache = $expected_build + [ + $expected_build_with_expected_cache = $expected_build + [ '#cache' => [ 'contexts' => [], 'tags' => [ @@ -137,7 +137,7 @@ class BlockComponentRenderArrayTest extends UnitTestCase { $result = $event->getBuild(); $this->assertEquals($expected_build, $result); $event->getCacheableMetadata()->applyTo($result); - $this->assertEquals($expected_cache, $result); + $this->assertEqualsCanonicalizing($expected_build_with_expected_cache['#cache'], $result['#cache']); } /** @@ -443,7 +443,7 @@ class BlockComponentRenderArrayTest extends UnitTestCase { $result = $event->getBuild(); $this->assertEquals($expected_build, $result); $event->getCacheableMetadata()->applyTo($result); - $this->assertEquals($expected_cache, $result); + $this->assertEqualsCanonicalizing($expected_cache, $result); } /** @@ -488,7 +488,7 @@ class BlockComponentRenderArrayTest extends UnitTestCase { $result = $event->getBuild(); $this->assertEquals($expected_build, $result); $event->getCacheableMetadata()->applyTo($result); - $this->assertEquals($expected_cache, $result); + $this->assertEqualsCanonicalizing($expected_cache, $result); } /** diff --git a/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php index 91d0cf9c083..4483b89b3d4 100644 --- a/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php +++ b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTest.php @@ -34,8 +34,8 @@ class MediaEmbedFilterTest extends MediaEmbedFilterTestBase { $this->assertCount(1, $this->cssSelect('div[data-media-embed-test-view-mode="' . $expected_view_mode . '"]')); $this->assertHasAttributes($this->cssSelect('div[data-media-embed-test-view-mode="' . $expected_view_mode . '"]')[0], $expected_attributes); - $this->assertSame($expected_cacheability->getCacheTags(), $result->getCacheTags()); - $this->assertSame($expected_cacheability->getCacheContexts(), $result->getCacheContexts()); + $this->assertEqualsCanonicalizing($expected_cacheability->getCacheTags(), $result->getCacheTags()); + $this->assertEqualsCanonicalizing($expected_cacheability->getCacheContexts(), $result->getCacheContexts()); $this->assertSame($expected_cacheability->getCacheMaxAge(), $result->getCacheMaxAge()); $this->assertSame(['library'], array_keys($result->getAttachments())); $this->assertSame(['media/filter.caption'], $result->getAttachments()['library']); @@ -152,8 +152,8 @@ class MediaEmbedFilterTest extends MediaEmbedFilterTestBase { $this->assertCount(1, $this->cssSelect('div[data-media-embed-test-view-mode="default"]')); } - $this->assertSame($expected_cacheability->getCacheTags(), $result->getCacheTags()); - $this->assertSame($expected_cacheability->getCacheContexts(), $result->getCacheContexts()); + $this->assertEqualsCanonicalizing($expected_cacheability->getCacheTags(), $result->getCacheTags()); + $this->assertEqualsCanonicalizing($expected_cacheability->getCacheContexts(), $result->getCacheContexts()); $this->assertSame($expected_cacheability->getCacheMaxAge(), $result->getCacheMaxAge()); $this->assertSame($expected_attachments, $result->getAttachments()); } @@ -408,7 +408,7 @@ class MediaEmbedFilterTest extends MediaEmbedFilterTestBase { $this->setRawContent($result->getProcessedText()); $this->assertCount($expected_verification_success ? 1 : 0, $this->cssSelect($verification_selector)); $this->assertCount(1, $this->cssSelect('div[data-media-embed-test-view-mode="default"]')); - $this->assertSame([ + $this->assertEqualsCanonicalizing([ '_media_test_embed_filter_access:media:1', '_media_test_embed_filter_access:user:2', 'config:image.style.thumbnail', @@ -417,7 +417,7 @@ class MediaEmbedFilterTest extends MediaEmbedFilterTestBase { 'media_view', 'user:2', ], $result->getCacheTags()); - $this->assertSame(['timezone', 'user.permissions'], $result->getCacheContexts()); + $this->assertEqualsCanonicalizing(['timezone', 'user.permissions'], $result->getCacheContexts()); $this->assertSame(Cache::PERMANENT, $result->getCacheMaxAge()); $this->assertSame(['library'], array_keys($result->getAttachments())); $this->assertSame($expected_asset_libraries, $result->getAttachments()['library']); diff --git a/core/modules/media/tests/src/Kernel/MediaEmbedFilterTranslationTest.php b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTranslationTest.php index 3ab1d9b2499..2031eefa946 100644 --- a/core/modules/media/tests/src/Kernel/MediaEmbedFilterTranslationTest.php +++ b/core/modules/media/tests/src/Kernel/MediaEmbedFilterTranslationTest.php @@ -62,7 +62,7 @@ class MediaEmbedFilterTranslationTest extends MediaEmbedFilterTestBase { // based on the host entity's language, which should require a cache context // to be associated. (The host entity's language may itself be selected // based on the request context, but that is of no concern to this filter.) - $this->assertSame($result->getCacheContexts(), ['timezone', 'user.permissions']); + $this->assertEqualsCanonicalizing($result->getCacheContexts(), ['timezone', 'user.permissions']); } /** diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php index 6db18eb9c3b..b8fa3d268c2 100644 --- a/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php +++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php @@ -417,8 +417,8 @@ class MediaLibraryAccessTest extends KernelTestBase { if ($access_result instanceof AccessResultReasonInterface && isset($expected_reason)) { $this->assertSame($expected_reason, $access_result->getReason()); } - $this->assertSame($expected_cache_tags, $access_result->getCacheTags()); - $this->assertSame($expected_cache_contexts, $access_result->getCacheContexts()); + $this->assertEqualsCanonicalizing($expected_cache_tags, $access_result->getCacheTags()); + $this->assertEqualsCanonicalizing($expected_cache_contexts, $access_result->getCacheContexts()); } } diff --git a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php index a14da184dce..27b49b27ee8 100644 --- a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php +++ b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php @@ -124,7 +124,7 @@ class MenuLinkContentCacheabilityBubblingTest extends KernelTestBase { $renderer->renderRoot($build); $expected_cacheability = $default_menu_cacheability->merge($expectation['cacheability']); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromRenderArray($build)); + $this->assertEqualsCanonicalizing($expected_cacheability, BubbleableMetadata::createFromRenderArray($build)); $menu_link_content->delete(); } @@ -146,7 +146,7 @@ class MenuLinkContentCacheabilityBubblingTest extends KernelTestBase { $build = $menu_tree->build($tree); $renderer->renderRoot($build); $expected_cacheability = $expected_cacheability->merge($default_menu_cacheability); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromRenderArray($build)); + $this->assertEqualsCanonicalizing($expected_cacheability, BubbleableMetadata::createFromRenderArray($build)); } } diff --git a/core/modules/node/tests/src/Kernel/NodeListBuilderTest.php b/core/modules/node/tests/src/Kernel/NodeListBuilderTest.php index f1f755a8e90..11f1a286453 100644 --- a/core/modules/node/tests/src/Kernel/NodeListBuilderTest.php +++ b/core/modules/node/tests/src/Kernel/NodeListBuilderTest.php @@ -33,7 +33,7 @@ class NodeListBuilderTest extends KernelTestBase { $build = $list_builder->render(); $this->container->get('renderer')->renderRoot($build); - $this->assertEquals(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view', 'user.permissions'], $build['#cache']['contexts']); + $this->assertEqualsCanonicalizing(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view', 'user.permissions'], $build['#cache']['contexts']); } } diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index e9ca8d6a172..e3df96112dc 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -565,7 +565,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase { static::recursiveKSort($expected); $actual = $this->serializer->decode((string) $response->getBody(), static::$format); static::recursiveKSort($actual); - $this->assertSame($expected, $actual); + $this->assertEqualsCanonicalizing($expected, $actual); // Not only assert the normalization, also assert deserialization of the // response results in the expected object. diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php index f9cfb1e169f..ce509970d54 100644 --- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php @@ -398,13 +398,13 @@ abstract class ResourceTestBase extends BrowserTestBase { // Expected cache tags: X-Drupal-Cache-Tags header. $this->assertSame($expected_cache_tags !== FALSE, $response->hasHeader('X-Drupal-Cache-Tags')); if (is_array($expected_cache_tags)) { - $this->assertSame($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0])); + $this->assertEqualsCanonicalizing($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0])); } // Expected cache contexts: X-Drupal-Cache-Contexts header. $this->assertSame($expected_cache_contexts !== FALSE, $response->hasHeader('X-Drupal-Cache-Contexts')); if (is_array($expected_cache_contexts)) { - $this->assertSame($expected_cache_contexts, explode(' ', $response->getHeader('X-Drupal-Cache-Contexts')[0])); + $this->assertEqualsCanonicalizing($expected_cache_contexts, explode(' ', $response->getHeader('X-Drupal-Cache-Contexts')[0])); } // Expected Page Cache header value: X-Drupal-Cache header. diff --git a/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php index 2175ee5f8fd..23bbb6f38ff 100644 --- a/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php @@ -177,7 +177,7 @@ class EntityTestTextItemNormalizerTest extends EntityTestResourceTestBase { $this->setUpAuthorization('GET'); $response = $this->request('GET', $url, $request_options); $expected_cache_tags = Cache::mergeTags($expected_cache_tags, parent::getExpectedCacheTags()); - $this->assertSame($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0])); + $this->assertEqualsCanonicalizing($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0])); } public function providerTestGetWithFormat() { diff --git a/core/modules/system/tests/src/Functional/Entity/EntityCacheTagsTestBase.php b/core/modules/system/tests/src/Functional/Entity/EntityCacheTagsTestBase.php index af96555a7a1..e5b8dc2494a 100644 --- a/core/modules/system/tests/src/Functional/Entity/EntityCacheTagsTestBase.php +++ b/core/modules/system/tests/src/Functional/Entity/EntityCacheTagsTestBase.php @@ -427,7 +427,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase { $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags); // Verify the entity type's list cache contexts are present. $contexts_in_header = $this->getSession()->getResponseHeader('X-Drupal-Cache-Contexts'); - $this->assertEquals(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); + $this->assertEqualsCanonicalizing(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); // Prime the page cache for the listing containing the referenced entity. $this->verifyPageCache($nonempty_entity_listing_url, 'MISS', $nonempty_entity_listing_cache_tags); @@ -435,7 +435,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase { $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags); // Verify the entity type's list cache contexts are present. $contexts_in_header = $this->getSession()->getResponseHeader('X-Drupal-Cache-Contexts'); - $this->assertEquals(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); + $this->assertEqualsCanonicalizing(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); // Verify that after modifying the referenced entity, there is a cache miss // for every route except the one for the non-referencing entity. diff --git a/core/modules/system/tests/src/Functional/Entity/EntityListBuilderTest.php b/core/modules/system/tests/src/Functional/Entity/EntityListBuilderTest.php index b4c90a3419a..5905701bedd 100644 --- a/core/modules/system/tests/src/Functional/Entity/EntityListBuilderTest.php +++ b/core/modules/system/tests/src/Functional/Entity/EntityListBuilderTest.php @@ -68,7 +68,7 @@ class EntityListBuilderTest extends BrowserTestBase { $build = $list_builder->render(); $this->container->get('renderer')->renderRoot($build); - $this->assertEquals(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.permissions'], $build['#cache']['contexts']); + $this->assertEqualsCanonicalizing(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.permissions'], $build['#cache']['contexts']); } /** diff --git a/core/modules/system/tests/src/Functional/Routing/RouterTest.php b/core/modules/system/tests/src/Functional/Routing/RouterTest.php index 945cabddb3b..1c2733798d1 100644 --- a/core/modules/system/tests/src/Functional/Routing/RouterTest.php +++ b/core/modules/system/tests/src/Functional/Routing/RouterTest.php @@ -34,6 +34,7 @@ class RouterTest extends BrowserTestBase { public function testFinishResponseSubscriber() { $renderer_required_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; $expected_cache_contexts = Cache::mergeContexts($renderer_required_cache_contexts, ['url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT]); + sort($expected_cache_contexts); // Confirm that the router can get to a controller. $this->drupalGet('router_test/test1'); @@ -65,12 +66,19 @@ class RouterTest extends BrowserTestBase { // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags headers. // 1. controller result: render array, globally cacheable route access. $this->drupalGet('router_test/test18'); - $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Contexts', implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url']))); + $expected_cache_contexts = Cache::mergeContexts($renderer_required_cache_contexts, ['url']); + sort($expected_cache_contexts); + $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Contexts', implode(' ', $expected_cache_contexts)); $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Tags', 'config:user.role.anonymous foo http_response rendered'); $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Max-Age', '60'); // 2. controller result: render array, per-role cacheable route access. $this->drupalGet('router_test/test19'); - $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Contexts', implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url', 'user.roles']))); + $expected_cache_contexts = Cache::mergeContexts($renderer_required_cache_contexts, [ + 'url', + 'user.roles', + ]); + sort($expected_cache_contexts); + $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Contexts', implode(' ', $expected_cache_contexts)); $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Tags', 'config:user.role.anonymous foo http_response rendered'); // 3. controller result: Response object, globally cacheable route access. $this->drupalGet('router_test/test1'); diff --git a/core/modules/system/tests/src/Kernel/Common/UrlTest.php b/core/modules/system/tests/src/Kernel/Common/UrlTest.php index e7482480976..295fb1ecaae 100644 --- a/core/modules/system/tests/src/Kernel/Common/UrlTest.php +++ b/core/modules/system/tests/src/Kernel/Common/UrlTest.php @@ -68,7 +68,7 @@ class UrlTest extends KernelTestBase { '#url' => Url::fromUri($uri), ]; \Drupal::service('renderer')->renderRoot($link); - $this->assertEquals($expected_cacheability, $link['#cache']); + $this->assertEqualsCanonicalizing($expected_cacheability, $link['#cache']); $this->assertEquals($expected_attachments, $link['#attached']); } } diff --git a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php index ca5cc68fb9b..6a6081f94c1 100644 --- a/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php +++ b/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php @@ -151,8 +151,8 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { $breadcrumb = $this->builder->build($this->createMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); - $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -168,8 +168,8 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { $breadcrumb = $this->builder->build($this->createMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); - $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -203,12 +203,12 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { $breadcrumb = $this->builder->build($this->createMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Example', new Url('example'))], $breadcrumb->getLinks()); - $this->assertEquals([ + $this->assertEqualsCanonicalizing([ 'url.path.is_front', 'url.path.parent', 'user.permissions', ], $breadcrumb->getCacheContexts()); - $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -258,13 +258,13 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { new Link('Example', new Url('example')), new Link('Bar', new Url('example_bar')), ], $breadcrumb->getLinks()); - $this->assertEquals([ + $this->assertEqualsCanonicalizing([ 'bar', 'url.path.is_front', 'url.path.parent', 'user.permissions', ], $breadcrumb->getCacheContexts()); - $this->assertEquals(['example'], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['example'], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -290,8 +290,8 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { // No path matched, though at least the frontpage is displayed. $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); - $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -334,8 +334,8 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { // No path matched, though at least the frontpage is displayed. $this->assertEquals([0 => new Link('Home', new Url(''))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); - $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -382,12 +382,12 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase { $breadcrumb = $this->builder->build($this->createMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url('')), 1 => new Link('Admin', new Url('user_page'))], $breadcrumb->getLinks()); - $this->assertEquals([ + $this->assertEqualsCanonicalizing([ 'url.path.is_front', 'url.path.parent', 'user.permissions', ], $breadcrumb->getCacheContexts()); - $this->assertEquals([], $breadcrumb->getCacheTags()); + $this->assertEqualsCanonicalizing([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } diff --git a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php index fd878e7eaa2..a3275470d4a 100644 --- a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php +++ b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php @@ -101,7 +101,6 @@ class MenuLinkTreeTest extends UnitTestCase { $access->addCacheContexts($access_cache_contexts); } $build = $this->menuLinkTree->build($tree); - sort($expected_build['#cache']['contexts']); $this->assertEquals($expected_build, $build, $description); } diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php index bd412ce1ff7..fbb159bdcc5 100644 --- a/core/modules/views/src/Entity/View.php +++ b/core/modules/views/src/Entity/View.php @@ -334,6 +334,8 @@ class View extends ConfigEntityBase implements ViewEntityInterface { // Always include at least the 'languages:' context as there will most // probably be translatable strings in the view output. $display['cache_metadata']['contexts'] = Cache::mergeContexts($display['cache_metadata']['contexts'], ['languages:' . LanguageInterface::TYPE_INTERFACE]); + sort($display['cache_metadata']['tags']); + sort($display['cache_metadata']['contexts']); } // Restore the previous active display. $executable->setDisplay($current_display); diff --git a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php index 050a1651d8c..d443e3ba277 100644 --- a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php +++ b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php @@ -52,7 +52,7 @@ trait AssertViewsCacheTagsTrait { // Check render array cache tags. sort($expected_render_array_cache_tags); - $this->assertEquals($expected_render_array_cache_tags, $build['#cache']['tags']); + $this->assertEqualsCanonicalizing($expected_render_array_cache_tags, $build['#cache']['tags']); if ($views_caching_is_enabled) { // Check Views render cache item cache tags. @@ -67,8 +67,7 @@ trait AssertViewsCacheTagsTrait { if (is_array($expected_results_cache)) { $this->assertNotEmpty($results_cache_item, 'Results cache item found.'); if ($results_cache_item) { - sort($expected_results_cache); - $this->assertEquals($expected_results_cache, $results_cache_item->tags); + $this->assertEqualsCanonicalizing($expected_results_cache, $results_cache_item->tags); } } else { @@ -83,7 +82,7 @@ trait AssertViewsCacheTagsTrait { if ($views_caching_is_enabled === TRUE) { $this->assertNotEmpty($render_cache_item, 'Render cache item found.'); if ($render_cache_item) { - $this->assertEquals($expected_render_array_cache_tags, $render_cache_item['#cache']['tags']); + $this->assertEqualsCanonicalizing($expected_render_array_cache_tags, $render_cache_item['#cache']['tags']); } } else { @@ -131,8 +130,7 @@ trait AssertViewsCacheTagsTrait { $renderer->renderRoot($build); // Check render array cache tags. - sort($expected_render_array_cache_tags); - $this->assertEquals($expected_render_array_cache_tags, $build['#cache']['tags']); + $this->assertEqualsCanonicalizing($expected_render_array_cache_tags, $build['#cache']['tags']); // Check Views render cache item cache tags. $original['#cache'] += ['contexts' => []]; @@ -142,7 +140,7 @@ trait AssertViewsCacheTagsTrait { if ($views_caching_is_enabled) { $this->assertTrue(!empty($render_cache_item), 'Render cache item found.'); if ($render_cache_item) { - $this->assertEquals($expected_render_array_cache_tags, $render_cache_item['#cache']['tags']); + $this->assertEqualsCanonicalizing($expected_render_array_cache_tags, $render_cache_item['#cache']['tags']); } } else { diff --git a/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php b/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php index 662a5e73640..46897992b1f 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FieldRenderedEntityTest.php @@ -144,7 +144,7 @@ class FieldRenderedEntityTest extends ViewsKernelTestBase { * The render array */ protected function assertCacheabilityMetadata($build) { - $this->assertEquals([ + $this->assertEqualsCanonicalizing([ 'config:core.entity_view_display.entity_test.entity_test.foobar', 'config:views.view.test_field_entity_test_rendered', 'entity_test:1', @@ -154,7 +154,7 @@ class FieldRenderedEntityTest extends ViewsKernelTestBase { 'entity_test_view', ], $build['#cache']['tags']); - $this->assertEquals([ + $this->assertEqualsCanonicalizing([ 'entity_test_view_grants', 'languages:language_interface', 'theme', diff --git a/core/modules/views/tests/src/Kernel/RenderCacheIntegrationTest.php b/core/modules/views/tests/src/Kernel/RenderCacheIntegrationTest.php index 1b04d4157f0..ed1fa20e285 100644 --- a/core/modules/views/tests/src/Kernel/RenderCacheIntegrationTest.php +++ b/core/modules/views/tests/src/Kernel/RenderCacheIntegrationTest.php @@ -285,7 +285,7 @@ class RenderCacheIntegrationTest extends ViewsKernelTestBase { $view = View::load('test_display'); $view->save(); - $this->assertEquals(['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'url.query_args', 'user.node_grants:view', 'user.permissions'], $view->getDisplay('default')['cache_metadata']['contexts']); + $this->assertEqualsCanonicalizing(['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'url.query_args', 'user.node_grants:view', 'user.permissions'], $view->getDisplay('default')['cache_metadata']['contexts']); } } diff --git a/core/modules/views/tests/src/Unit/Plugin/query/SqlTest.php b/core/modules/views/tests/src/Unit/Plugin/query/SqlTest.php index 0ef02fb6616..875cf47f19f 100644 --- a/core/modules/views/tests/src/Unit/Plugin/query/SqlTest.php +++ b/core/modules/views/tests/src/Unit/Plugin/query/SqlTest.php @@ -69,7 +69,7 @@ class SqlTest extends UnitTestCase { $result[] = $row; $view->result = $result; - $this->assertEquals(['entity_test:123', 'entity_test:124', 'entity_test:125', 'entity_test:126'], $query->getCacheTags()); + $this->assertEqualsCanonicalizing(['entity_test:123', 'entity_test:124', 'entity_test:125', 'entity_test:126'], $query->getCacheTags()); } /** diff --git a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php index 5056c86b907..ec7260dba90 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php @@ -404,8 +404,8 @@ class AccessResultTest extends UnitTestCase { $this->assertFalse($access->isForbidden()); $this->assertTrue($access->isNeutral()); $this->assertSame(Cache::PERMANENT, $access->getCacheMaxAge()); - $this->assertSame($contexts, $access->getCacheContexts()); - $this->assertSame([], $access->getCacheTags()); + $this->assertEqualsCanonicalizing($contexts, $access->getCacheContexts()); + $this->assertEqualsCanonicalizing([], $access->getCacheTags()); }; $access = AccessResult::neutral()->addCacheContexts(['foo']); @@ -451,7 +451,7 @@ class AccessResultTest extends UnitTestCase { $verify($b, $contexts); $c = AccessResult::neutral()->cachePerUser()->cachePerPermissions(); $verify($c, $contexts); - $this->assertEquals($a, $b); + $this->assertEqualsCanonicalizing($a, $b); $this->assertEquals($a, $c); // ::allowIfHasPermission and ::allowedIfHasPermission convenience methods. @@ -480,8 +480,8 @@ class AccessResultTest extends UnitTestCase { $this->assertFalse($access->isForbidden()); $this->assertTrue($access->isNeutral()); $this->assertSame($max_age, $access->getCacheMaxAge()); - $this->assertSame($contexts, $access->getCacheContexts()); - $this->assertSame($tags, $access->getCacheTags()); + $this->assertEqualsCanonicalizing($contexts, $access->getCacheContexts()); + $this->assertEqualsCanonicalizing($tags, $access->getCacheTags()); }; $access = AccessResult::neutral()->addCacheTags(['foo:bar']); diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php index 12dc9bb5399..458eddcc99a 100644 --- a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php @@ -52,11 +52,11 @@ class CacheTest extends UnitTestCase { return [ [[], [], []], [['bar', 'foo'], ['bar'], ['foo']], - [['bar', 'foo'], ['foo'], ['bar']], - [['bar', 'foo'], ['foo'], ['bar', 'foo']], - [['bar', 'foo'], ['foo'], ['foo', 'bar']], + [['foo', 'bar'], ['foo'], ['bar']], + [['foo', 'bar'], ['foo'], ['bar', 'foo']], + [['foo', 'bar'], ['foo'], ['foo', 'bar']], [['bar', 'foo'], ['bar', 'foo'], ['foo', 'bar']], - [['bar', 'foo'], ['foo', 'bar'], ['foo', 'bar']], + [['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar']], [['bar', 'foo', 'llama'], ['bar', 'foo'], ['foo', 'bar'], ['llama', 'foo']], ]; } @@ -67,7 +67,7 @@ class CacheTest extends UnitTestCase { * @dataProvider mergeTagsProvider */ public function testMergeTags(array $expected, ...$cache_tags) { - $this->assertEquals($expected, Cache::mergeTags(...$cache_tags)); + $this->assertEqualsCanonicalizing($expected, Cache::mergeTags(...$cache_tags)); } /** @@ -145,7 +145,7 @@ class CacheTest extends UnitTestCase { $container = $this->prophesize(Container::class); $container->get('cache_contexts_manager')->willReturn($cache_contexts_manager->reveal()); \Drupal::setContainer($container->reveal()); - $this->assertSame($expected, Cache::mergeContexts(...$contexts)); + $this->assertEqualsCanonicalizing($expected, Cache::mergeContexts(...$contexts)); } /** diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php index b59e996f9af..c04bed5b902 100644 --- a/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/CacheableMetadataTest.php @@ -35,7 +35,7 @@ class CacheableMetadataTest extends UnitTestCase { $container->set('cache_contexts_manager', $cache_contexts_manager); \Drupal::setContainer($container); - $this->assertEquals($expected, $a->merge($b)); + $this->assertEqualsCanonicalizing($expected, $a->merge($b)); } /** @@ -58,7 +58,7 @@ class CacheableMetadataTest extends UnitTestCase { $container->set('cache_contexts_manager', $cache_contexts_manager); \Drupal::setContainer($container); - $this->assertEquals($expected, $a->addCacheableDependency($b)); + $this->assertEqualsCanonicalizing($expected, $a->addCacheableDependency($b)); } /** @@ -73,7 +73,7 @@ class CacheableMetadataTest extends UnitTestCase { // Cache contexts. [(new CacheableMetadata())->setCacheContexts(['foo']), (new CacheableMetadata())->setCacheContexts(['bar']), (new CacheableMetadata())->setCacheContexts(['bar', 'foo'])], // Cache tags. - [(new CacheableMetadata())->setCacheTags(['foo']), (new CacheableMetadata())->setCacheTags(['bar']), (new CacheableMetadata())->setCacheTags(['bar', 'foo'])], + [(new CacheableMetadata())->setCacheTags(['foo']), (new CacheableMetadata())->setCacheTags(['bar']), (new CacheableMetadata())->setCacheTags(['foo', 'bar'])], // Cache max-ages. [(new CacheableMetadata())->setCacheMaxAge(60), (new CacheableMetadata())->setCacheMaxAge(Cache::PERMANENT), (new CacheableMetadata())->setCacheMaxAge(60)], ]; @@ -90,15 +90,15 @@ class CacheableMetadataTest extends UnitTestCase { [[], []], [['foo:bar'], ['foo:bar']], [['foo:baz'], ['foo:bar', 'foo:baz']], - [['axx:first', 'foo:baz'], ['axx:first', 'foo:bar', 'foo:baz']], - [[], ['axx:first', 'foo:bar', 'foo:baz']], - [['axx:first'], ['axx:first', 'foo:bar', 'foo:baz']], + [['axx:first', 'foo:baz'], ['foo:bar', 'foo:baz', 'axx:first']], + [[], ['foo:bar', 'foo:baz', 'axx:first']], + [['axx:first'], ['foo:bar', 'foo:baz', 'axx:first']], ]; - foreach ($add_expected as $data) { + foreach ($add_expected as $row => $data) { list($add, $expected) = $data; $metadata->addCacheTags($add); - $this->assertEquals($expected, $metadata->getCacheTags()); + $this->assertEquals($expected, $metadata->getCacheTags(), sprintf("Dataset in %d row failed on validation.", $row + 1)); } } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php index 16ef3d1c68f..e56202d81ca 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php @@ -406,10 +406,10 @@ class EntityUnitTest extends UnitTestCase { ], [ [ - // Own cache tag. - $this->entityTypeId . ':' . $this->values['id'], // List cache tag. $this->entityTypeId . '_list', + // Own cache tag. + $this->entityTypeId . ':' . $this->values['id'], ], ]); @@ -438,11 +438,11 @@ class EntityUnitTest extends UnitTestCase { ], [ [ - // Own cache tag. - $this->entityTypeId . ':' . $this->values['id'], // List cache tag. $this->entityTypeId . '_list', $this->entityTypeId . '_list:' . $this->entity->bundle(), + // Own cache tag. + $this->entityTypeId . ':' . $this->values['id'], ], ]); @@ -500,8 +500,8 @@ class EntityUnitTest extends UnitTestCase { $this->cacheTagsInvalidator->expects($this->once()) ->method('invalidateTags') ->with([ - $this->entityTypeId . ':' . $this->values['id'], $this->entityTypeId . '_list', + $this->entityTypeId . ':' . $this->values['id'], ]); $storage = $this->createMock('\Drupal\Core\Entity\EntityStorageInterface'); $storage->expects($this->once()) @@ -518,11 +518,16 @@ class EntityUnitTest extends UnitTestCase { public function testPostDeleteBundle() { $this->cacheTagsInvalidator->expects($this->once()) ->method('invalidateTags') - ->with([ - $this->entityTypeId . ':' . $this->values['id'], - $this->entityTypeId . '_list', - $this->entityTypeId . '_list:' . $this->entity->bundle(), - ]); + // with() also asserts on the order of array values and array keys that + // is something we should avoid here. + ->willReturnCallback(function (array $tags) { + self::assertEqualsCanonicalizing([ + $this->entityTypeId . '_list', + $this->entityTypeId . ':' . $this->values['id'], + $this->entityTypeId . '_list:' . $this->entity->bundle(), + ], $tags); + return NULL; + }); $this->entityType->expects($this->atLeastOnce()) ->method('hasKey') ->with('bundle') @@ -561,8 +566,8 @@ class EntityUnitTest extends UnitTestCase { */ public function testCacheTags() { // Ensure that both methods return the same by default. - $this->assertEquals([$this->entityTypeId . ':' . 1], $this->entity->getCacheTags()); - $this->assertEquals([$this->entityTypeId . ':' . 1], $this->entity->getCacheTagsToInvalidate()); + $this->assertEqualsCanonicalizing([$this->entityTypeId . ':' . 1], $this->entity->getCacheTags()); + $this->assertEqualsCanonicalizing([$this->entityTypeId . ':' . 1], $this->entity->getCacheTagsToInvalidate()); // Add an additional cache tag and make sure only getCacheTags() returns // that. @@ -570,10 +575,9 @@ class EntityUnitTest extends UnitTestCase { // EntityTypeId is random so it can shift order. We need to duplicate the // sort from \Drupal\Core\Cache\Cache::mergeTags(). - $tags = ['additional_cache_tag', $this->entityTypeId . ':' . 1]; - sort($tags); - $this->assertEquals($tags, $this->entity->getCacheTags()); - $this->assertEquals([$this->entityTypeId . ':' . 1], $this->entity->getCacheTagsToInvalidate()); + $tags = [$this->entityTypeId . ':' . 1, 'additional_cache_tag']; + $this->assertEqualsCanonicalizing($tags, $this->entity->getCacheTags()); + $this->assertEqualsCanonicalizing([$this->entityTypeId . ':' . 1], $this->entity->getCacheTagsToInvalidate()); } /** @@ -591,11 +595,11 @@ class EntityUnitTest extends UnitTestCase { \Drupal::setContainer($container); // There are no cache contexts by default. - $this->assertEquals([], $this->entity->getCacheContexts()); + $this->assertEqualsCanonicalizing([], $this->entity->getCacheContexts()); // Add an additional cache context. $this->entity->addCacheContexts(['user']); - $this->assertEquals(['user'], $this->entity->getCacheContexts()); + $this->assertEqualsCanonicalizing(['user'], $this->entity->getCacheContexts()); } /** diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php index e7c58a847c4..cfba3cb61a7 100644 --- a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php @@ -434,8 +434,8 @@ class LocalTaskManagerTest extends UnitTestCase { $this->manager->getTasksBuild('menu_local_task_test_tasks_view', $cacheability); // Ensure that all cacheability metadata is merged together. - $this->assertEquals(['tag.example1', 'tag.example2'], $cacheability->getCacheTags()); - $this->assertEquals(['context.example1', 'context.example2', 'route', 'user.permissions'], $cacheability->getCacheContexts()); + $this->assertEqualsCanonicalizing(['tag.example1', 'tag.example2'], $cacheability->getCacheTags()); + $this->assertEqualsCanonicalizing(['context.example1', 'context.example2', 'route', 'user.permissions'], $cacheability->getCacheContexts()); } protected function setupFactoryAndLocalTaskPlugins(array $definitions, $active_plugin_id) { @@ -476,7 +476,7 @@ class LocalTaskManagerTest extends UnitTestCase { $cache_context_manager = $this->prophesize(CacheContextsManager::class); - foreach ([NULL, ['user.permissions'], ['route'], ['route', 'context.example1'], ['context.example1', 'route'], ['context.example1', 'route', 'context.example2'], ['context.example1', 'context.example2', 'route'], ['context.example1', 'context.example2', 'route', 'user.permissions']] as $argument) { + foreach ([NULL, ['user.permissions'], ['route'], ['route', 'context.example1'], ['context.example1', 'route'], ['route', 'context.example1', 'context.example2'], ['context.example1', 'context.example2', 'route'], ['route', 'context.example1', 'context.example2', 'user.permissions']] as $argument) { $cache_context_manager->assertValidTokens($argument)->willReturn(TRUE); } diff --git a/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php b/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php index 84acf154bb1..9dd18541861 100644 --- a/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php +++ b/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php @@ -60,7 +60,7 @@ class BubbleableMetadataTest extends UnitTestCase { $container->set('renderer', $renderer); \Drupal::setContainer($container); - $this->assertEquals($expected, $a->merge($b)); + $this->assertEqualsCanonicalizing($expected, $a->merge($b)); } /** @@ -76,7 +76,7 @@ class BubbleableMetadataTest extends UnitTestCase { // Cache contexts. [(new BubbleableMetadata())->setCacheContexts(['foo']), (new BubbleableMetadata())->setCacheContexts(['bar']), (new BubbleableMetadata())->setCacheContexts(['bar', 'foo'])], // Cache tags. - [(new BubbleableMetadata())->setCacheTags(['foo']), (new BubbleableMetadata())->setCacheTags(['bar']), (new BubbleableMetadata())->setCacheTags(['bar', 'foo'])], + [(new BubbleableMetadata())->setCacheTags(['foo']), (new BubbleableMetadata())->setCacheTags(['bar']), (new BubbleableMetadata())->setCacheTags(['foo', 'bar'])], // Cache max-ages. [(new BubbleableMetadata())->setCacheMaxAge(60), (new BubbleableMetadata())->setCacheMaxAge(Cache::PERMANENT), (new BubbleableMetadata())->setCacheMaxAge(60)], // Assets. @@ -90,7 +90,7 @@ class BubbleableMetadataTest extends UnitTestCase { // Cache contexts. [(new BubbleableMetadata())->setCacheContexts(['foo']), (new CacheableMetadata())->setCacheContexts(['bar']), (new BubbleableMetadata())->setCacheContexts(['bar', 'foo'])], // Cache tags. - [(new BubbleableMetadata())->setCacheTags(['foo']), (new CacheableMetadata())->setCacheTags(['bar']), (new BubbleableMetadata())->setCacheTags(['bar', 'foo'])], + [(new BubbleableMetadata())->setCacheTags(['foo']), (new CacheableMetadata())->setCacheTags(['bar']), (new BubbleableMetadata())->setCacheTags(['foo', 'bar'])], // Cache max-ages. [(new BubbleableMetadata())->setCacheMaxAge(60), (new CacheableMetadata())->setCacheMaxAge(Cache::PERMANENT), (new BubbleableMetadata())->setCacheMaxAge(60)], ]; @@ -661,7 +661,7 @@ class BubbleableMetadataTest extends UnitTestCase { $container->set('cache_contexts_manager', $cache_contexts_manager); \Drupal::setContainer($container); - $this->assertEquals($expected, $a->addCacheableDependency($b)); + $this->assertEqualsCanonicalizing($expected, $a->addCacheableDependency($b)); } /** diff --git a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php index d09d45136f1..a49ed7b26bc 100644 --- a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php @@ -119,7 +119,7 @@ class RendererBubblingTest extends RendererTestBase { '#cache_redirect' => TRUE, '#cache' => [ 'keys' => ['parent'], - 'contexts' => ['bar', 'foo'], + 'contexts' => ['foo', 'bar'], 'tags' => [], 'bin' => $bin, 'max-age' => 3600, @@ -143,7 +143,7 @@ class RendererBubblingTest extends RendererTestBase { $this->renderer->renderRoot($element); - $this->assertEquals($expected_top_level_contexts, $element['#cache']['contexts'], 'Expected cache contexts found.'); + $this->assertEqualsCanonicalizing($expected_top_level_contexts, $element['#cache']['contexts'], 'Expected cache contexts found.'); foreach ($expected_cache_items as $cid => $expected_cache_item) { $this->assertRenderCacheItem($cid, $expected_cache_item); } @@ -211,7 +211,6 @@ class RendererBubblingTest extends RendererTestBase { ]; foreach ($context_orders as $context_order) { $test_element['#cache']['contexts'] = $context_order; - sort($context_order); $expected_cache_items['set_test:bar:baz:foo']['#cache']['contexts'] = $context_order; $data[] = [$test_element, $context_order, $expected_cache_items]; } @@ -235,7 +234,7 @@ class RendererBubblingTest extends RendererTestBase { 'parent:bar:baz:foo' => [ '#attached' => [], '#cache' => [ - 'contexts' => ['bar', 'baz', 'foo'], + 'contexts' => ['foo', 'bar', 'baz'], 'tags' => [], 'max-age' => 3600, ], @@ -274,8 +273,8 @@ class RendererBubblingTest extends RendererTestBase { '#cache' => [ // The keys + contexts this redirects to. 'keys' => ['parent'], - 'contexts' => ['bar', 'foo'], - 'tags' => ['dee', 'fiddle', 'har', 'yar'], + 'contexts' => ['foo', 'bar'], + 'tags' => ['yar', 'har', 'fiddle', 'dee'], 'bin' => 'render', 'max-age' => Cache::PERMANENT, ], @@ -283,8 +282,8 @@ class RendererBubblingTest extends RendererTestBase { 'parent:bar:foo' => [ '#attached' => [], '#cache' => [ - 'contexts' => ['bar', 'foo'], - 'tags' => ['dee', 'fiddle', 'har', 'yar'], + 'contexts' => ['foo', 'bar'], + 'tags' => ['yar', 'har', 'fiddle', 'dee'], 'max-age' => Cache::PERMANENT, ], '#markup' => 'parent', @@ -320,7 +319,7 @@ class RendererBubblingTest extends RendererTestBase { '#attached' => ['library' => ['foo/bar']], '#cache' => [ 'contexts' => ['foo'], - 'tags' => ['dee', 'fiddle', 'har', 'yar'], + 'tags' => ['yar', 'har', 'fiddle', 'dee'], 'max-age' => Cache::PERMANENT, ], '#markup' => 'parent', @@ -412,7 +411,7 @@ class RendererBubblingTest extends RendererTestBase { '#cache_redirect' => TRUE, '#cache' => [ 'keys' => ['parent'], - 'contexts' => ['foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo'], 'tags' => ['a', 'b', 'c'], 'bin' => 'render', 'max-age' => 1800, @@ -421,7 +420,7 @@ class RendererBubblingTest extends RendererTestBase { $this->assertRenderCacheItem('parent:foo:r.B', [ '#attached' => [], '#cache' => [ - 'contexts' => ['foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo'], 'tags' => ['a', 'b', 'c'], 'max-age' => 1800, ], @@ -445,7 +444,7 @@ class RendererBubblingTest extends RendererTestBase { '#cache_redirect' => TRUE, '#cache' => [ 'keys' => ['parent'], - 'contexts' => ['foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo'], 'tags' => ['a', 'b', 'c'], 'bin' => 'render', 'max-age' => 1800, @@ -454,7 +453,7 @@ class RendererBubblingTest extends RendererTestBase { $this->assertRenderCacheItem('parent:foo:r.A', [ '#attached' => [], '#cache' => [ - 'contexts' => ['foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo'], 'tags' => ['a', 'b'], // Note that the max-age here is unaffected. When role A, the grandchild // is never rendered, so neither is its max-age of 1800 present here, @@ -474,7 +473,7 @@ class RendererBubblingTest extends RendererTestBase { '#cache_redirect' => TRUE, '#cache' => [ 'keys' => ['parent'], - 'contexts' => ['bar', 'foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo', 'bar'], 'tags' => ['a', 'b', 'c', 'd'], 'bin' => 'render', 'max-age' => 300, @@ -484,7 +483,7 @@ class RendererBubblingTest extends RendererTestBase { $this->assertRenderCacheItem('parent:bar:foo:r.C', [ '#attached' => [], '#cache' => [ - 'contexts' => ['bar', 'foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo', 'bar'], 'tags' => ['a', 'b', 'c', 'd'], 'max-age' => 300, ], @@ -499,7 +498,7 @@ class RendererBubblingTest extends RendererTestBase { $this->assertRenderCacheItem('parent:bar:foo:r.A', [ '#attached' => [], '#cache' => [ - 'contexts' => ['bar', 'foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo', 'bar'], 'tags' => ['a', 'b'], // Note that the max-age here is unaffected. When role A, the grandchild // is never rendered, so neither is its max-age of 1800 present here, @@ -518,7 +517,7 @@ class RendererBubblingTest extends RendererTestBase { $this->assertRenderCacheItem('parent:bar:foo:r.B', [ '#attached' => [], '#cache' => [ - 'contexts' => ['bar', 'foo', 'user.roles'], + 'contexts' => ['user.roles', 'foo', 'bar'], 'tags' => ['a', 'b', 'c'], // Note that the max-age here is unaffected. When role B, the // grandgrandchild is never rendered, so neither is its max-age of 300 diff --git a/core/tests/Drupal/Tests/Core/Render/RendererTest.php b/core/tests/Drupal/Tests/Core/Render/RendererTest.php index 7d519335c7d..c67e9a7558d 100644 --- a/core/tests/Drupal/Tests/Core/Render/RendererTest.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererTest.php @@ -632,7 +632,7 @@ class RendererTest extends RendererTestBase { $this->renderer->renderPlain($build); - $this->assertEquals(['languages:language_interface', 'theme', 'user'], $build['#cache']['contexts']); + $this->assertEqualsCanonicalizing(['languages:language_interface', 'theme', 'user'], $build['#cache']['contexts']); } /** diff --git a/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php b/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php index 198f2963173..d667d1ddc8f 100644 --- a/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererTestBase.php @@ -250,8 +250,18 @@ abstract class RendererTestBase extends UnitTestCase { $cached = $cache_backend->get($cid); $this->assertNotFalse($cached, sprintf('Expected cache item "%s" exists.', $cid)); if ($cached !== FALSE) { - $this->assertEquals($data, $cached->data, sprintf('Cache item "%s" has the expected data.', $cid)); - $this->assertSame(Cache::mergeTags($data['#cache']['tags'], ['rendered']), $cached->tags, "The cache item's cache tags also has the 'rendered' cache tag."); + $this->assertEqualsCanonicalizing(array_keys($data), array_keys($cached->data), 'The cache item contains the same parent array keys.'); + foreach ($data as $key => $value) { + // We do not want to assert on the order of cacheability information. + // @see https://www.drupal.org/project/drupal/issues/3225328 + if ($key === '#cache') { + $this->assertEqualsCanonicalizing($value, $cached->data[$key], sprintf('Cache item "%s" has the expected data.', $cid)); + } + else { + $this->assertEquals($value, $cached->data[$key], sprintf('Cache item "%s" has the expected data.', $cid)); + } + } + $this->assertEqualsCanonicalizing(Cache::mergeTags($data['#cache']['tags'], ['rendered']), $cached->tags, "The cache item's cache tags also has the 'rendered' cache tag."); } }