diff --git a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
index 1243118..79ca932 100644
--- a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
@@ -67,6 +67,20 @@ class RegistryTest extends UnitTestCase {
   protected $themeManager;
 
   /**
+   * The theme.
+   *
+   * @var \Drupal\Core\Theme\ThemeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $theme;
+
+  /**
+   * The list of functions that get_defined_functions() should provide.
+   *
+   * @var array
+   */
+  public static $functions = [];
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
@@ -83,6 +97,14 @@ protected function setUp() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  protected function tearDown() {
+    parent::tearDown();
+    static::$functions = [];
+  }
+
+  /**
    * Tests getting the theme registry defined by a module.
    */
   public function testGetRegistryForModule() {
@@ -159,6 +181,137 @@ public function testGetRegistryForModule() {
     $this->assertTrue(in_array('test_stable_preprocess_theme_test_render_element', $other_registry['theme_test_render_element']['preprocess functions']));
   }
 
+  /**
+   * Sets up the mocks needed for testing Registry::postProcessExtension.
+   */
+  public function setUpPostProcessExtension() {
+    $this->theme = $this->getMockBuilder(ActiveTheme::class)
+      ->disableOriginalConstructor()
+      ->getMock();
+    $this->theme->expects($this->atLeastOnce())
+      ->method('getBaseThemes')
+      ->will($this->returnValue([]));
+    $this->theme->expects($this->atLeastOnce())
+      ->method('getName')
+      ->will($this->returnValue('test'));
+
+    $this->moduleHandler->expects($this->atLeastOnce())
+      ->method('getModuleList')
+      ->willReturn([]);
+  }
+
+  /**
+   * Tests that preprocess functions are added when base hook is specified.
+   *
+   * @covers ::postProcessExtension
+   */
+  public function testManualBaseHook() {
+    static::$functions['user'] = ['cat', 'mouse', 'cheese'];
+
+    // Define a test case registry with mock data.
+    $hooks = [
+      'test_hook' => [
+        'preprocess functions' => ['cat', 'mouse'],
+      ],
+      'test_hook_manual' => [
+        'preprocess functions' => ['cheese'],
+        'base hook' => 'test_hook',
+        'incomplete preprocess functions' => TRUE,
+      ],
+    ];
+
+    $expected = [
+      'test_hook' => [
+        'preprocess functions' => ['cat', 'mouse'],
+      ],
+      'test_hook_manual' => [
+        'preprocess functions' => ['cat', 'mouse', 'cheese'],
+        'base hook' => 'test_hook',
+      ],
+    ];
+
+    $this->setUpPostProcessExtension();
+
+    $class = new \ReflectionClass(TestRegistry::class);
+    $reflection_method = $class->getMethod('postProcessExtension');
+    $reflection_method->setAccessible(TRUE);
+    $reflection_method->invokeArgs($this->registry, [ &$hooks, $this->theme]);
+
+    $this->assertArrayEquals($hooks, $expected);
+  }
+
+  /**
+   * Tests that a suggestion defined in hook_theme gets preprocess functions.
+   *
+   * @covers ::postProcessExtension
+   */
+  public function testManualSuggestion() {
+    $this->setUpPostProcessExtension();
+
+    $hooks = [
+      'test_hook' => [
+        'preprocess functions' => ['cat', 'mouse'],
+        'template' => 'test-hook',
+      ],
+      'test_hook__suggestion' => [
+        'preprocess functions' => ['bread'],
+        'incomplete preprocess functions' => TRUE,
+      ],
+      'test_hook__suggestion__another' => [
+        'preprocess functions' => ['cheese'],
+        'incomplete preprocess functions' => TRUE,
+      ],
+    ];
+
+    $expected = [
+      'test_hook' => [
+        'preprocess functions' => [
+          'cat',
+          'mouse',
+        ],
+        'template' => 'test-hook',
+      ],
+      'test_hook__suggestion' => [
+        'preprocess functions' => [
+          'cat',
+          'mouse',
+          'bread',
+          'test_preprocess_test_hook__suggestion',
+        ],
+        'base hook' => 'test_hook',
+        'template' => 'test-hook',
+      ],
+      'test_hook__suggestion__another' => [
+        'preprocess functions' => [
+          'cat',
+          'mouse',
+          'bread',
+          'test_preprocess_test_hook__suggestion',
+          'cheese',
+          'test_preprocess_test_hook__suggestion__another',
+        ],
+        'base hook' => 'test_hook',
+        'template' => 'test-hook',
+      ],
+    ];
+
+    static::$functions['user'] = [
+      'cat',
+      'mouse',
+      'cheese',
+      'bread',
+      'test_preprocess_test_hook__suggestion',
+      'test_preprocess_test_hook__suggestion__another',
+    ];
+
+    $class = new \ReflectionClass(TestRegistry::class);
+    $reflection_method = $class->getMethod('postProcessExtension');
+    $reflection_method->setAccessible(TRUE);
+    $reflection_method->invokeArgs($this->registry, [&$hooks, $this->theme]);
+
+    $this->assertArrayEquals($hooks, $expected);
+  }
+
   protected function setupTheme() {
     $this->registry = new TestRegistry($this->root, $this->cache, $this->lock, $this->moduleHandler, $this->themeHandler, $this->themeInitialization);
     $this->registry->setThemeManager($this->themeManager);
@@ -175,3 +328,14 @@ protected function getPath($module) {
   }
 
 }
+
+namespace Drupal\Core\Theme;
+
+use Drupal\Tests\Core\Theme\RegistryTest;
+
+/**
+ * Overrides get_defined_functions() with a configurable mock.
+ */
+function get_defined_functions() {
+  return RegistryTest::$functions ?: \get_defined_functions();
+}
