From 9d552cad6cfbe8383b96b74ffc6176503a7b0c2e Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Thu, 4 Jan 2018 07:37:32 +1000
Subject: [PATCH] Issue #2926309 by vaplas, alexpott, mpdonadio, tacituseu,
 Mixologic: Random fail due to APCu not being able to allocate memory

---
 core/lib/Drupal/Core/Site/Settings.php           |  6 ++++--
 .../Core/Test/FunctionalTestSetupTrait.php       | 16 ++++++++++++++++
 .../src/Functional/Module/ClassLoaderTest.php    |  5 +++++
 .../Drupal/Tests/Core/Site/SettingsTest.php      |  2 +-
 4 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php
index a1a6c38893e..bdd2609a7c0 100644
--- a/core/lib/Drupal/Core/Site/Settings.php
+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -156,8 +156,8 @@ final class Settings {
    * cache. By default, this method will produce a unique prefix per site using
    * the hash salt. If the setting 'apcu_ensure_unique_prefix' is set to FALSE
    * then if the caller does not provide a $site_path only the Drupal root will
-   * be used. This allows WebTestBase to use the same prefix ensuring that the
-   * number of APCu items created during a full test run is kept to a minimum.
+   * be used. This allows tests to use the same prefix ensuring that the number
+   * of APCu items created during a full test run is kept to a minimum.
    * Additionally, if a multi site implementation does not use site specific
    * module directories setting apcu_ensure_unique_prefix would allow the sites
    * to share APCu cache items.
@@ -168,6 +168,8 @@ final class Settings {
    *
    * @return string
    *   The prefix for APCu user cache keys.
+   *
+   * @see https://www.drupal.org/project/drupal/issues/2926309
    */
   public static function getApcuPrefix($identifier, $root, $site_path = '') {
     if (static::get('apcu_ensure_unique_prefix', TRUE)) {
diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
index f9f97ecaa8c..3165815b175 100644
--- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
+++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
@@ -41,6 +41,18 @@ trait FunctionalTestSetupTrait {
    */
   protected $configDirectories = [];
 
+  /**
+   * The flag to set 'apcu_ensure_unique_prefix' setting.
+   *
+   * Wide use of a unique prefix can lead to problems with memory, if tests are
+   * run with a concurrency higher than 1. Therefore, FALSE by default.
+   *
+   * @var bool
+   *
+   * @see \Drupal\Core\Site\Settings::getApcuPrefix().
+   */
+  protected $apcuEnsureUniquePrefix = FALSE;
+
   /**
    * Prepares site settings and services before installation.
    */
@@ -83,6 +95,10 @@ trait FunctionalTestSetupTrait {
       'value' => $this->originalProfile,
       'required' => TRUE,
     ];
+    $settings['settings']['apcu_ensure_unique_prefix'] = (object) [
+      'value' => $this->apcuEnsureUniquePrefix,
+      'required' => TRUE,
+    ];
     $this->writeSettings($settings);
     // Allow for test-specific overrides.
     $settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSite . '/settings.testing.php';
diff --git a/core/modules/system/tests/src/Functional/Module/ClassLoaderTest.php b/core/modules/system/tests/src/Functional/Module/ClassLoaderTest.php
index 93c0bf3f422..335a03a329b 100644
--- a/core/modules/system/tests/src/Functional/Module/ClassLoaderTest.php
+++ b/core/modules/system/tests/src/Functional/Module/ClassLoaderTest.php
@@ -18,6 +18,11 @@ class ClassLoaderTest extends BrowserTestBase {
    */
   protected $expected = 'Drupal\\module_autoload_test\\SomeClass::testMethod() was invoked.';
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $apcuEnsureUniquePrefix = TRUE;
+
   /**
    * Tests that module-provided classes can be loaded when a module is enabled.
    *
diff --git a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
index 5e4f1d084c1..f72e4ce9f0e 100644
--- a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
+++ b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
@@ -117,7 +117,7 @@ class SettingsTest extends UnitTestCase {
    * @covers ::getApcuPrefix
    */
   public function testGetApcuPrefix() {
-    $settings = new Settings(['hash_salt' => 123]);
+    $settings = new Settings(['hash_salt' => 123, 'apcu_ensure_unique_prefix' => TRUE]);
     $this->assertNotEquals($settings::getApcuPrefix('cache_test', '/test/a'), $settings::getApcuPrefix('cache_test', '/test/b'));
 
     $settings = new Settings(['hash_salt' => 123, 'apcu_ensure_unique_prefix' => FALSE]);