diff --git a/core/modules/system/lib/Drupal/system/Tests/System/ThemeInterfaceTest.php b/core/modules/system/lib/Drupal/system/Tests/System/ThemeInterfaceTest.php
new file mode 100644
index 0000000..27078dc
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/System/ThemeInterfaceTest.php
@@ -0,0 +1,244 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\System\ThemeTest.
+ */
+
+namespace Drupal\system\Tests\System;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests for the theme interface functionality.
+ */
+class ThemeInterfaceTest extends WebTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Theme interface functionality',
+      'description' => 'Tests the theme interface functionality by enabling and switching themes, and using an administration theme.',
+      'group' => 'System',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('node', 'block'));
+
+    $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
+
+    $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'view the administration theme', 'administer themes', 'bypass node access', 'administer blocks'));
+    $this->drupalLogin($this->admin_user);
+    $this->node = $this->drupalCreateNode();
+  }
+
+  /**
+   * Test the theme settings form.
+   */
+  function testThemeSettings() {
+    // Specify a filesystem path to be used for the logo.
+    $file = current($this->drupalGetTestFiles('image'));
+    $file_relative = strtr($file->uri, array('public:/' => variable_get('file_public_path', conf_path() . '/files')));
+    $default_theme_path = 'core/themes/stark';
+
+    $supported_paths = array(
+      // Raw stream wrapper URI.
+      $file->uri => array(
+        'form' => file_uri_target($file->uri),
+        'src' => file_create_url($file->uri),
+      ),
+      // Relative path within the public filesystem.
+      file_uri_target($file->uri) => array(
+        'form' => file_uri_target($file->uri),
+        'src' => file_create_url($file->uri),
+      ),
+      // Relative path to a public file.
+      $file_relative => array(
+        'form' => $file_relative,
+        'src' => file_create_url($file->uri),
+      ),
+      // Relative path to an arbitrary file.
+      'core/misc/druplicon.png' => array(
+        'form' => 'core/misc/druplicon.png',
+        'src' => $GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png',
+      ),
+      // Relative path to a file in a theme.
+      $default_theme_path . '/logo.png' => array(
+        'form' => $default_theme_path . '/logo.png',
+        'src' => $GLOBALS['base_url'] . '/' . $default_theme_path . '/logo.png',
+      ),
+    );
+    foreach ($supported_paths as $input => $expected) {
+      $edit = array(
+        'default_logo' => FALSE,
+        'logo_path' => $input,
+      );
+      $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration'));
+      $this->assertNoText('The custom logo path is invalid.');
+      $this->assertFieldByName('logo_path', $expected['form']);
+
+      // Verify logo path examples.
+      $elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array(
+        ':item' => 'form-item-logo-path',
+        ':description' => 'description',
+      ));
+      // Expected default values (if all else fails).
+      $implicit_public_file = 'logo.png';
+      $explicit_file = 'public://logo.png';
+      $local_file = $default_theme_path . '/logo.png';
+      // Adjust for fully qualified stream wrapper URI in public filesystem.
+      if (file_uri_scheme($input) == 'public') {
+        $implicit_public_file = file_uri_target($input);
+        $explicit_file = $input;
+        $local_file = strtr($input, array('public:/' => variable_get('file_public_path', conf_path() . '/files')));
+      }
+      // Adjust for fully qualified stream wrapper URI elsewhere.
+      elseif (file_uri_scheme($input) !== FALSE) {
+        $explicit_file = $input;
+      }
+      // Adjust for relative path within public filesystem.
+      elseif ($input == file_uri_target($file->uri)) {
+        $implicit_public_file = $input;
+        $explicit_file = 'public://' . $input;
+        $local_file = variable_get('file_public_path', conf_path() . '/files') . '/' . $input;
+      }
+      $this->assertEqual((string) $elements[0], $implicit_public_file);
+      $this->assertEqual((string) $elements[1], $explicit_file);
+      $this->assertEqual((string) $elements[2], $local_file);
+
+      // Verify the actual 'src' attribute of the logo being output.
+      $this->drupalGet('');
+      $elements = $this->xpath('//*[@id=:id]/img', array(':id' => 'logo'));
+      $this->assertEqual((string) $elements[0]['src'], $expected['src']);
+    }
+
+    $unsupported_paths = array(
+      // Stream wrapper URI to non-existing file.
+      'public://whatever.png',
+      'private://whatever.png',
+      'temporary://whatever.png',
+      // Bogus stream wrapper URIs.
+      'public:/whatever.png',
+      '://whatever.png',
+      ':whatever.png',
+      'public://',
+      // Relative path within the public filesystem to non-existing file.
+      'whatever.png',
+      // Relative path to non-existing file in public filesystem.
+      variable_get('file_public_path', conf_path() . '/files') . '/whatever.png',
+      // Semi-absolute path to non-existing file in public filesystem.
+      '/' . variable_get('file_public_path', conf_path() . '/files') . '/whatever.png',
+      // Relative path to arbitrary non-existing file.
+      'core/misc/whatever.png',
+      // Semi-absolute path to arbitrary non-existing file.
+      '/core/misc/whatever.png',
+      // Absolute paths to any local file (even if it exists).
+      drupal_realpath($file->uri),
+    );
+    $this->drupalGet('admin/appearance/settings');
+    foreach ($unsupported_paths as $path) {
+      $edit = array(
+        'default_logo' => FALSE,
+        'logo_path' => $path,
+      );
+      $this->drupalPost(NULL, $edit, t('Save configuration'));
+      $this->assertText('The custom logo path is invalid.');
+    }
+
+    // Upload a file to use for the logo.
+    $edit = array(
+      'default_logo' => FALSE,
+      'logo_path' => '',
+      'files[logo_upload]' => drupal_realpath($file->uri),
+    );
+    $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration'));
+
+    $fields = $this->xpath($this->constructFieldXpath('name', 'logo_path'));
+    $uploaded_filename = 'public://' . $fields[0]['value'];
+
+    $this->drupalGet('');
+    $elements = $this->xpath('//*[@id=:id]/img', array(':id' => 'logo'));
+    $this->assertEqual($elements[0]['src'], file_create_url($uploaded_filename));
+  }
+
+  /**
+   * Test the administration theme functionality.
+   */
+  function testAdministrationTheme() {
+    theme_enable(array('stark'));
+    variable_set('theme_default', 'stark');
+    // Enable an administration theme and show it on the node admin pages.
+    $edit = array(
+      'admin_theme' => 'seven',
+      'node_admin_theme' => TRUE,
+    );
+    $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
+
+    $this->drupalGet('admin/config');
+    $this->assertRaw('core/themes/seven', t('Administration theme used on an administration page.'));
+
+    $this->drupalGet('node/' . $this->node->nid);
+    $this->assertRaw('core/themes/stark', t('Site default theme used on node page.'));
+
+    $this->drupalGet('node/add');
+    $this->assertRaw('core/themes/seven', t('Administration theme used on the add content page.'));
+
+    $this->drupalGet('node/' . $this->node->nid . '/edit');
+    $this->assertRaw('core/themes/seven', t('Administration theme used on the edit content page.'));
+
+    // Disable the admin theme on the node admin pages.
+    $edit = array(
+      'node_admin_theme' => FALSE,
+    );
+    $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
+
+    $this->drupalGet('admin/config');
+    $this->assertRaw('core/themes/seven', t('Administration theme used on an administration page.'));
+
+    $this->drupalGet('node/add');
+    $this->assertRaw('core/themes/stark', t('Site default theme used on the add content page.'));
+
+    // Reset to the default theme settings.
+    variable_set('theme_default', 'bartik');
+    $edit = array(
+      'admin_theme' => '0',
+      'node_admin_theme' => FALSE,
+    );
+    $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
+
+    $this->drupalGet('admin');
+    $this->assertRaw('core/themes/bartik', t('Site default theme used on administration page.'));
+
+    $this->drupalGet('node/add');
+    $this->assertRaw('core/themes/bartik', t('Site default theme used on the add content page.'));
+  }
+
+  /**
+   * Test switching the default theme.
+   */
+  function testSwitchDefaultTheme() {
+    // Enable Bartik and set it as the default theme.
+    theme_enable(array('bartik'));
+    $this->drupalGet('admin/appearance');
+    $this->clickLink(t('Set default'));
+    $this->assertEqual(variable_get('theme_default', ''), 'bartik');
+
+    // Test the default theme on the secondary links (blocks admin page).
+    $this->drupalGet('admin/structure/block');
+    $this->assertText('Bartik(' . t('active tab') . ')', t('Default local task on blocks admin page is the default theme.'));
+    // Switch back to Stark and test again to test that the menu cache is cleared.
+    $this->drupalGet('admin/appearance');
+    $this->clickLink(t('Set default'), 0);
+    $this->drupalGet('admin/structure/block');
+    $this->assertText('Stark(' . t('active tab') . ')', t('Default local task on blocks admin page has changed.'));
+  }
+
+  /**
+   * Test that themes can't be enabled when the base theme or engine is missing.
+   */
+  function testInvalidTheme() {
+    module_enable(array('theme_page_test'));
+    $this->drupalGet('admin/appearance');
+    $this->assertText(t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => 'not_real_test_basetheme')), 'Invalid base theme check succeeded.');
+    $this->assertText(t('This theme requires the theme engine @theme_engine to operate correctly.', array('@theme_engine' => 'not_real_engine')), 'Invalid theme engine check succeeded.');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/ThemeTest.php b/core/modules/system/lib/Drupal/system/Tests/System/ThemeTest.php
deleted file mode 100644
index ed43e49..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/System/ThemeTest.php
+++ /dev/null
@@ -1,244 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\System\ThemeTest.
- */
-
-namespace Drupal\system\Tests\System;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests for the theme interface functionality.
- */
-class ThemeTest extends WebTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Theme interface functionality',
-      'description' => 'Tests the theme interface functionality by enabling and switching themes, and using an administration theme.',
-      'group' => 'System',
-    );
-  }
-
-  function setUp() {
-    parent::setUp(array('node', 'block'));
-
-    $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
-
-    $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'view the administration theme', 'administer themes', 'bypass node access', 'administer blocks'));
-    $this->drupalLogin($this->admin_user);
-    $this->node = $this->drupalCreateNode();
-  }
-
-  /**
-   * Test the theme settings form.
-   */
-  function testThemeSettings() {
-    // Specify a filesystem path to be used for the logo.
-    $file = current($this->drupalGetTestFiles('image'));
-    $file_relative = strtr($file->uri, array('public:/' => variable_get('file_public_path', conf_path() . '/files')));
-    $default_theme_path = 'core/themes/stark';
-
-    $supported_paths = array(
-      // Raw stream wrapper URI.
-      $file->uri => array(
-        'form' => file_uri_target($file->uri),
-        'src' => file_create_url($file->uri),
-      ),
-      // Relative path within the public filesystem.
-      file_uri_target($file->uri) => array(
-        'form' => file_uri_target($file->uri),
-        'src' => file_create_url($file->uri),
-      ),
-      // Relative path to a public file.
-      $file_relative => array(
-        'form' => $file_relative,
-        'src' => file_create_url($file->uri),
-      ),
-      // Relative path to an arbitrary file.
-      'core/misc/druplicon.png' => array(
-        'form' => 'core/misc/druplicon.png',
-        'src' => $GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png',
-      ),
-      // Relative path to a file in a theme.
-      $default_theme_path . '/logo.png' => array(
-        'form' => $default_theme_path . '/logo.png',
-        'src' => $GLOBALS['base_url'] . '/' . $default_theme_path . '/logo.png',
-      ),
-    );
-    foreach ($supported_paths as $input => $expected) {
-      $edit = array(
-        'default_logo' => FALSE,
-        'logo_path' => $input,
-      );
-      $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration'));
-      $this->assertNoText('The custom logo path is invalid.');
-      $this->assertFieldByName('logo_path', $expected['form']);
-
-      // Verify logo path examples.
-      $elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array(
-        ':item' => 'form-item-logo-path',
-        ':description' => 'description',
-      ));
-      // Expected default values (if all else fails).
-      $implicit_public_file = 'logo.png';
-      $explicit_file = 'public://logo.png';
-      $local_file = $default_theme_path . '/logo.png';
-      // Adjust for fully qualified stream wrapper URI in public filesystem.
-      if (file_uri_scheme($input) == 'public') {
-        $implicit_public_file = file_uri_target($input);
-        $explicit_file = $input;
-        $local_file = strtr($input, array('public:/' => variable_get('file_public_path', conf_path() . '/files')));
-      }
-      // Adjust for fully qualified stream wrapper URI elsewhere.
-      elseif (file_uri_scheme($input) !== FALSE) {
-        $explicit_file = $input;
-      }
-      // Adjust for relative path within public filesystem.
-      elseif ($input == file_uri_target($file->uri)) {
-        $implicit_public_file = $input;
-        $explicit_file = 'public://' . $input;
-        $local_file = variable_get('file_public_path', conf_path() . '/files') . '/' . $input;
-      }
-      $this->assertEqual((string) $elements[0], $implicit_public_file);
-      $this->assertEqual((string) $elements[1], $explicit_file);
-      $this->assertEqual((string) $elements[2], $local_file);
-
-      // Verify the actual 'src' attribute of the logo being output.
-      $this->drupalGet('');
-      $elements = $this->xpath('//*[@id=:id]/img', array(':id' => 'logo'));
-      $this->assertEqual((string) $elements[0]['src'], $expected['src']);
-    }
-
-    $unsupported_paths = array(
-      // Stream wrapper URI to non-existing file.
-      'public://whatever.png',
-      'private://whatever.png',
-      'temporary://whatever.png',
-      // Bogus stream wrapper URIs.
-      'public:/whatever.png',
-      '://whatever.png',
-      ':whatever.png',
-      'public://',
-      // Relative path within the public filesystem to non-existing file.
-      'whatever.png',
-      // Relative path to non-existing file in public filesystem.
-      variable_get('file_public_path', conf_path() . '/files') . '/whatever.png',
-      // Semi-absolute path to non-existing file in public filesystem.
-      '/' . variable_get('file_public_path', conf_path() . '/files') . '/whatever.png',
-      // Relative path to arbitrary non-existing file.
-      'core/misc/whatever.png',
-      // Semi-absolute path to arbitrary non-existing file.
-      '/core/misc/whatever.png',
-      // Absolute paths to any local file (even if it exists).
-      drupal_realpath($file->uri),
-    );
-    $this->drupalGet('admin/appearance/settings');
-    foreach ($unsupported_paths as $path) {
-      $edit = array(
-        'default_logo' => FALSE,
-        'logo_path' => $path,
-      );
-      $this->drupalPost(NULL, $edit, t('Save configuration'));
-      $this->assertText('The custom logo path is invalid.');
-    }
-
-    // Upload a file to use for the logo.
-    $edit = array(
-      'default_logo' => FALSE,
-      'logo_path' => '',
-      'files[logo_upload]' => drupal_realpath($file->uri),
-    );
-    $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration'));
-
-    $fields = $this->xpath($this->constructFieldXpath('name', 'logo_path'));
-    $uploaded_filename = 'public://' . $fields[0]['value'];
-
-    $this->drupalGet('');
-    $elements = $this->xpath('//*[@id=:id]/img', array(':id' => 'logo'));
-    $this->assertEqual($elements[0]['src'], file_create_url($uploaded_filename));
-  }
-
-  /**
-   * Test the administration theme functionality.
-   */
-  function testAdministrationTheme() {
-    theme_enable(array('stark'));
-    variable_set('theme_default', 'stark');
-    // Enable an administration theme and show it on the node admin pages.
-    $edit = array(
-      'admin_theme' => 'seven',
-      'node_admin_theme' => TRUE,
-    );
-    $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
-
-    $this->drupalGet('admin/config');
-    $this->assertRaw('core/themes/seven', t('Administration theme used on an administration page.'));
-
-    $this->drupalGet('node/' . $this->node->nid);
-    $this->assertRaw('core/themes/stark', t('Site default theme used on node page.'));
-
-    $this->drupalGet('node/add');
-    $this->assertRaw('core/themes/seven', t('Administration theme used on the add content page.'));
-
-    $this->drupalGet('node/' . $this->node->nid . '/edit');
-    $this->assertRaw('core/themes/seven', t('Administration theme used on the edit content page.'));
-
-    // Disable the admin theme on the node admin pages.
-    $edit = array(
-      'node_admin_theme' => FALSE,
-    );
-    $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
-
-    $this->drupalGet('admin/config');
-    $this->assertRaw('core/themes/seven', t('Administration theme used on an administration page.'));
-
-    $this->drupalGet('node/add');
-    $this->assertRaw('core/themes/stark', t('Site default theme used on the add content page.'));
-
-    // Reset to the default theme settings.
-    variable_set('theme_default', 'bartik');
-    $edit = array(
-      'admin_theme' => '0',
-      'node_admin_theme' => FALSE,
-    );
-    $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
-
-    $this->drupalGet('admin');
-    $this->assertRaw('core/themes/bartik', t('Site default theme used on administration page.'));
-
-    $this->drupalGet('node/add');
-    $this->assertRaw('core/themes/bartik', t('Site default theme used on the add content page.'));
-  }
-
-  /**
-   * Test switching the default theme.
-   */
-  function testSwitchDefaultTheme() {
-    // Enable Bartik and set it as the default theme.
-    theme_enable(array('bartik'));
-    $this->drupalGet('admin/appearance');
-    $this->clickLink(t('Set default'));
-    $this->assertEqual(variable_get('theme_default', ''), 'bartik');
-
-    // Test the default theme on the secondary links (blocks admin page).
-    $this->drupalGet('admin/structure/block');
-    $this->assertText('Bartik(' . t('active tab') . ')', t('Default local task on blocks admin page is the default theme.'));
-    // Switch back to Stark and test again to test that the menu cache is cleared.
-    $this->drupalGet('admin/appearance');
-    $this->clickLink(t('Set default'), 0);
-    $this->drupalGet('admin/structure/block');
-    $this->assertText('Stark(' . t('active tab') . ')', t('Default local task on blocks admin page has changed.'));
-  }
-
-  /**
-   * Test that themes can't be enabled when the base theme or engine is missing.
-   */
-  function testInvalidTheme() {
-    module_enable(array('theme_page_test'));
-    $this->drupalGet('admin/appearance');
-    $this->assertText(t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => 'not_real_test_basetheme')), 'Invalid base theme check succeeded.');
-    $this->assertText(t('This theme requires the theme engine @theme_engine to operate correctly.', array('@theme_engine' => 'not_real_engine')), 'Invalid theme engine check succeeded.');
-  }
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeAPITest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeAPITest.php
new file mode 100644
index 0000000..432b232
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeAPITest.php
@@ -0,0 +1,182 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Theme\ThemeTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\test_theme\ThemeClass;
+
+/**
+ * Tests low-level theme functions.
+ */
+class ThemeAPITest extends WebTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Theme API',
+      'description' => 'Test low-level theme functions.',
+      'group' => 'Theme',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('theme_test');
+    theme_enable(array('test_theme'));
+  }
+
+  /**
+   * Test function theme_get_suggestions() for SA-CORE-2009-003.
+   */
+  function testThemeSuggestions() {
+    // Set the front page as something random otherwise the CLI
+    // test runner fails.
+    config('system.site')->set('page.front', 'nobody-home')->save();
+    $args = array('node', '1', 'edit');
+    $suggestions = theme_get_suggestions($args, 'page');
+    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1', 'page__node__edit'), t('Found expected node edit page suggestions'));
+    // Check attack vectors.
+    $args = array('node', '\\1');
+    $suggestions = theme_get_suggestions($args, 'page');
+    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), t('Removed invalid \\ from suggestions'));
+    $args = array('node', '1/');
+    $suggestions = theme_get_suggestions($args, 'page');
+    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), t('Removed invalid / from suggestions'));
+    $args = array('node', "1\0");
+    $suggestions = theme_get_suggestions($args, 'page');
+    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), t('Removed invalid \\0 from suggestions'));
+    // Define path with hyphens to be used to generate suggestions.
+    $args = array('node', '1', 'hyphen-path');
+    $result = array('page__node', 'page__node__%', 'page__node__1', 'page__node__hyphen_path');
+    $suggestions = theme_get_suggestions($args, 'page');
+    $this->assertEqual($suggestions, $result, t('Found expected page suggestions for paths containing hyphens.'));
+  }
+
+  /**
+   * Ensures preprocess functions run even for suggestion implementations.
+   *
+   * The theme hook used by this test has its base preprocess function in a
+   * separate file, so this test also ensures that that file is correctly loaded
+   * when needed.
+   */
+  function testPreprocessForSuggestions() {
+    // Test with both an unprimed and primed theme registry.
+    drupal_theme_rebuild();
+    for ($i = 0; $i < 2; $i++) {
+      $this->drupalGet('theme-test/suggestion');
+      $this->assertText('Theme hook implementor=test_theme_theme_test__suggestion(). Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.');
+    }
+  }
+
+  /**
+   * Ensure page-front template suggestion is added when on front page.
+   */
+  function testFrontPageThemeSuggestion() {
+    $original_path = _current_path();
+    // Set the current path to node because theme_get_suggestions() will query
+    // it to see if we are on the front page.
+    config('system.site')->set('page.front', 'node')->save();
+    _current_path('node');
+    $suggestions = theme_get_suggestions(array('node'), 'page');
+    // Set it back to not annoy the batch runner.
+    _current_path($original_path);
+    $this->assertTrue(in_array('page__front', $suggestions), t('Front page template was suggested.'));
+  }
+
+  /**
+   * Ensures theme hook_*_alter() implementations can run before anything is rendered.
+   */
+  function testAlter() {
+    $this->drupalGet('theme-test/alter');
+    $this->assertText('The altered data is test_theme_theme_test_alter_alter was invoked.', t('The theme was able to implement an alter hook during page building before anything was rendered.'));
+  }
+
+  /**
+   * Ensures a theme's .info file is able to override a module CSS file from being added to the page.
+   *
+   * @see test_theme.info
+   */
+  function testCSSOverride() {
+    // Reuse the same page as in testPreprocessForSuggestions(). We're testing
+    // what is output to the HTML HEAD based on what is in a theme's .info file,
+    // so it doesn't matter what page we get, as long as it is themed with the
+    // test theme. First we test with CSS aggregation disabled.
+    $config = config('system.performance');
+    $config->set('preprocess_css', 0);
+    $config->save();
+    $this->drupalGet('theme-test/suggestion');
+    $this->assertNoText('system.base.css', t('The theme\'s .info file is able to override a module CSS file from being added to the page.'));
+
+    // Also test with aggregation enabled, simply ensuring no PHP errors are
+    // triggered during drupal_build_css_cache() when a source file doesn't
+    // exist. Then allow remaining tests to continue with aggregation disabled
+    // by default.
+    $config->set('preprocess_css', 1);
+    $config->save();
+    $this->drupalGet('theme-test/suggestion');
+    $config->set('preprocess_css', 0);
+    $config->save();
+  }
+
+  /**
+   * Ensures a themes template is overrideable based on the 'template' filename.
+   */
+  function testTemplateOverride() {
+    variable_set('theme_default', 'test_theme');
+    $this->drupalGet('theme-test/template-test');
+    $this->assertText('Success: Template overridden.', t('Template overridden by defined \'template\' filename.'));
+  }
+
+  /**
+   * Test the list_themes() function.
+   */
+  function testListThemes() {
+    $themes = list_themes();
+    // Check if drupal_theme_access() retrieves enabled themes properly from list_themes().
+    $this->assertTrue(drupal_theme_access('test_theme'), t('Enabled theme detected'));
+    // Check if list_themes() returns disabled themes.
+    $this->assertTrue(array_key_exists('test_basetheme', $themes), t('Disabled theme detected'));
+    // Check for base theme and subtheme lists.
+    $base_theme_list = array('test_basetheme' => 'Theme test base theme');
+    $sub_theme_list = array('test_subtheme' => 'Theme test subtheme');
+    $this->assertIdentical($themes['test_basetheme']->sub_themes, $sub_theme_list, t('Base theme\'s object includes list of subthemes.'));
+    $this->assertIdentical($themes['test_subtheme']->base_themes, $base_theme_list, t('Subtheme\'s object includes list of base themes.'));
+    // Check for theme engine in subtheme.
+    $this->assertIdentical($themes['test_subtheme']->engine, 'phptemplate', t('Subtheme\'s object includes the theme engine.'));
+    // Check for theme engine prefix.
+    $this->assertIdentical($themes['test_basetheme']->prefix, 'phptemplate', t('Base theme\'s object includes the theme engine prefix.'));
+    $this->assertIdentical($themes['test_subtheme']->prefix, 'phptemplate', t('Subtheme\'s object includes the theme engine prefix.'));
+  }
+
+  /**
+   * Test the theme_get_setting() function.
+   */
+  function testThemeGetSetting() {
+    $GLOBALS['theme_key'] = 'test_theme';
+    $this->assertIdentical(theme_get_setting('theme_test_setting'), 'default value', t('theme_get_setting() uses the default theme automatically.'));
+    $this->assertNotEqual(theme_get_setting('subtheme_override', 'test_basetheme'), theme_get_setting('subtheme_override', 'test_subtheme'), t('Base theme\'s default settings values can be overridden by subtheme.'));
+    $this->assertIdentical(theme_get_setting('basetheme_only', 'test_subtheme'), 'base theme value', t('Base theme\'s default settings values are inherited by subtheme.'));
+  }
+
+  /**
+   * Ensures the theme registry is rebuilt when modules are disabled/enabled.
+   */
+  function testRegistryRebuild() {
+    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'a')), 'a', 'The theme registry contains theme_test_foo.');
+
+    module_disable(array('theme_test'), FALSE);
+    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'b')), '', 'The theme registry does not contain theme_test_foo, because the module is disabled.');
+
+    module_enable(array('theme_test'), FALSE);
+    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'c')), 'c', 'The theme registry contains theme_test_foo again after re-enabling the module.');
+  }
+
+  /**
+   * Tests theme can provide classes.
+   */
+  function testClassLoading() {
+    new ThemeClass();
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
deleted file mode 100644
index 4be9dd5..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
+++ /dev/null
@@ -1,182 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Theme\ThemeTest.
- */
-
-namespace Drupal\system\Tests\Theme;
-
-use Drupal\simpletest\WebTestBase;
-use Drupal\test_theme\ThemeClass;
-
-/**
- * Tests low-level theme functions.
- */
-class ThemeTest extends WebTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Theme API',
-      'description' => 'Test low-level theme functions.',
-      'group' => 'Theme',
-    );
-  }
-
-  function setUp() {
-    parent::setUp('theme_test');
-    theme_enable(array('test_theme'));
-  }
-
-  /**
-   * Test function theme_get_suggestions() for SA-CORE-2009-003.
-   */
-  function testThemeSuggestions() {
-    // Set the front page as something random otherwise the CLI
-    // test runner fails.
-    config('system.site')->set('page.front', 'nobody-home')->save();
-    $args = array('node', '1', 'edit');
-    $suggestions = theme_get_suggestions($args, 'page');
-    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1', 'page__node__edit'), t('Found expected node edit page suggestions'));
-    // Check attack vectors.
-    $args = array('node', '\\1');
-    $suggestions = theme_get_suggestions($args, 'page');
-    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), t('Removed invalid \\ from suggestions'));
-    $args = array('node', '1/');
-    $suggestions = theme_get_suggestions($args, 'page');
-    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), t('Removed invalid / from suggestions'));
-    $args = array('node', "1\0");
-    $suggestions = theme_get_suggestions($args, 'page');
-    $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), t('Removed invalid \\0 from suggestions'));
-    // Define path with hyphens to be used to generate suggestions.
-    $args = array('node', '1', 'hyphen-path');
-    $result = array('page__node', 'page__node__%', 'page__node__1', 'page__node__hyphen_path');
-    $suggestions = theme_get_suggestions($args, 'page');
-    $this->assertEqual($suggestions, $result, t('Found expected page suggestions for paths containing hyphens.'));
-  }
-
-  /**
-   * Ensures preprocess functions run even for suggestion implementations.
-   *
-   * The theme hook used by this test has its base preprocess function in a
-   * separate file, so this test also ensures that that file is correctly loaded
-   * when needed.
-   */
-  function testPreprocessForSuggestions() {
-    // Test with both an unprimed and primed theme registry.
-    drupal_theme_rebuild();
-    for ($i = 0; $i < 2; $i++) {
-      $this->drupalGet('theme-test/suggestion');
-      $this->assertText('Theme hook implementor=test_theme_theme_test__suggestion(). Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.');
-    }
-  }
-
-  /**
-   * Ensure page-front template suggestion is added when on front page.
-   */
-  function testFrontPageThemeSuggestion() {
-    $original_path = _current_path();
-    // Set the current path to node because theme_get_suggestions() will query
-    // it to see if we are on the front page.
-    config('system.site')->set('page.front', 'node')->save();
-    _current_path('node');
-    $suggestions = theme_get_suggestions(array('node'), 'page');
-    // Set it back to not annoy the batch runner.
-    _current_path($original_path);
-    $this->assertTrue(in_array('page__front', $suggestions), t('Front page template was suggested.'));
-  }
-
-  /**
-   * Ensures theme hook_*_alter() implementations can run before anything is rendered.
-   */
-  function testAlter() {
-    $this->drupalGet('theme-test/alter');
-    $this->assertText('The altered data is test_theme_theme_test_alter_alter was invoked.', t('The theme was able to implement an alter hook during page building before anything was rendered.'));
-  }
-
-  /**
-   * Ensures a theme's .info file is able to override a module CSS file from being added to the page.
-   *
-   * @see test_theme.info
-   */
-  function testCSSOverride() {
-    // Reuse the same page as in testPreprocessForSuggestions(). We're testing
-    // what is output to the HTML HEAD based on what is in a theme's .info file,
-    // so it doesn't matter what page we get, as long as it is themed with the
-    // test theme. First we test with CSS aggregation disabled.
-    $config = config('system.performance');
-    $config->set('preprocess_css', 0);
-    $config->save();
-    $this->drupalGet('theme-test/suggestion');
-    $this->assertNoText('system.base.css', t('The theme\'s .info file is able to override a module CSS file from being added to the page.'));
-
-    // Also test with aggregation enabled, simply ensuring no PHP errors are
-    // triggered during drupal_build_css_cache() when a source file doesn't
-    // exist. Then allow remaining tests to continue with aggregation disabled
-    // by default.
-    $config->set('preprocess_css', 1);
-    $config->save();
-    $this->drupalGet('theme-test/suggestion');
-    $config->set('preprocess_css', 0);
-    $config->save();
-  }
-
-  /**
-   * Ensures a themes template is overrideable based on the 'template' filename.
-   */
-  function testTemplateOverride() {
-    variable_set('theme_default', 'test_theme');
-    $this->drupalGet('theme-test/template-test');
-    $this->assertText('Success: Template overridden.', t('Template overridden by defined \'template\' filename.'));
-  }
-
-  /**
-   * Test the list_themes() function.
-   */
-  function testListThemes() {
-    $themes = list_themes();
-    // Check if drupal_theme_access() retrieves enabled themes properly from list_themes().
-    $this->assertTrue(drupal_theme_access('test_theme'), t('Enabled theme detected'));
-    // Check if list_themes() returns disabled themes.
-    $this->assertTrue(array_key_exists('test_basetheme', $themes), t('Disabled theme detected'));
-    // Check for base theme and subtheme lists.
-    $base_theme_list = array('test_basetheme' => 'Theme test base theme');
-    $sub_theme_list = array('test_subtheme' => 'Theme test subtheme');
-    $this->assertIdentical($themes['test_basetheme']->sub_themes, $sub_theme_list, t('Base theme\'s object includes list of subthemes.'));
-    $this->assertIdentical($themes['test_subtheme']->base_themes, $base_theme_list, t('Subtheme\'s object includes list of base themes.'));
-    // Check for theme engine in subtheme.
-    $this->assertIdentical($themes['test_subtheme']->engine, 'phptemplate', t('Subtheme\'s object includes the theme engine.'));
-    // Check for theme engine prefix.
-    $this->assertIdentical($themes['test_basetheme']->prefix, 'phptemplate', t('Base theme\'s object includes the theme engine prefix.'));
-    $this->assertIdentical($themes['test_subtheme']->prefix, 'phptemplate', t('Subtheme\'s object includes the theme engine prefix.'));
-  }
-
-  /**
-   * Test the theme_get_setting() function.
-   */
-  function testThemeGetSetting() {
-    $GLOBALS['theme_key'] = 'test_theme';
-    $this->assertIdentical(theme_get_setting('theme_test_setting'), 'default value', t('theme_get_setting() uses the default theme automatically.'));
-    $this->assertNotEqual(theme_get_setting('subtheme_override', 'test_basetheme'), theme_get_setting('subtheme_override', 'test_subtheme'), t('Base theme\'s default settings values can be overridden by subtheme.'));
-    $this->assertIdentical(theme_get_setting('basetheme_only', 'test_subtheme'), 'base theme value', t('Base theme\'s default settings values are inherited by subtheme.'));
-  }
-
-  /**
-   * Ensures the theme registry is rebuilt when modules are disabled/enabled.
-   */
-  function testRegistryRebuild() {
-    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'a')), 'a', 'The theme registry contains theme_test_foo.');
-
-    module_disable(array('theme_test'), FALSE);
-    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'b')), '', 'The theme registry does not contain theme_test_foo, because the module is disabled.');
-
-    module_enable(array('theme_test'), FALSE);
-    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'c')), 'c', 'The theme registry contains theme_test_foo again after re-enabling the module.');
-  }
-
-  /**
-   * Tests theme can provide classes.
-   */
-  function testClassLoading() {
-    new ThemeClass();
-  }
-}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyThemeTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyThemeTest.php
new file mode 100644
index 0000000..d255aea
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyThemeTest.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\taxonomy\Tests\ThemeTest.
+ */
+
+namespace Drupal\taxonomy\Tests;
+
+/**
+ * Tests for verifying that taxonomy pages use the correct theme.
+ */
+class TaxonomyThemeTest extends TaxonomyTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Taxonomy theme switching',
+      'description' => 'Verifies that various taxonomy pages use the expected theme.',
+      'group' => 'Taxonomy',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Make sure we are using distinct default and administrative themes for
+    // the duration of these tests.
+    variable_set('theme_default', 'bartik');
+    variable_set('admin_theme', 'seven');
+
+    // Create and log in as a user who has permission to add and edit taxonomy
+    // terms and view the administrative theme.
+    $admin_user = $this->drupalCreateUser(array('administer taxonomy', 'view the administration theme'));
+    $this->drupalLogin($admin_user);
+  }
+
+  /**
+   * Test the theme used when adding, viewing and editing taxonomy terms.
+   */
+  function testTaxonomyTermThemes() {
+    // Adding a term to a vocabulary is considered an administrative action and
+    // should use the administrative theme.
+    $vocabulary = $this->createVocabulary();
+    $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add');
+    $this->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page for adding a taxonomy term."));
+
+    // Viewing a taxonomy term should use the default theme.
+    $term = $this->createTerm($vocabulary);
+    $this->drupalGet('taxonomy/term/' . $term->tid);
+    $this->assertRaw('bartik/css/style.css', t("The default theme's CSS appears on the page for viewing a taxonomy term."));
+
+    // Editing a taxonomy term should use the same theme as adding one.
+    $this->drupalGet('taxonomy/term/' . $term->tid . '/edit');
+    $this->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page for editing a taxonomy term."));
+  }
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/ThemeTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/ThemeTest.php
deleted file mode 100644
index baa5c61..0000000
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/ThemeTest.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\taxonomy\Tests\ThemeTest.
- */
-
-namespace Drupal\taxonomy\Tests;
-
-/**
- * Tests for verifying that taxonomy pages use the correct theme.
- */
-class ThemeTest extends TaxonomyTestBase {
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Taxonomy theme switching',
-      'description' => 'Verifies that various taxonomy pages use the expected theme.',
-      'group' => 'Taxonomy',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-
-    // Make sure we are using distinct default and administrative themes for
-    // the duration of these tests.
-    variable_set('theme_default', 'bartik');
-    variable_set('admin_theme', 'seven');
-
-    // Create and log in as a user who has permission to add and edit taxonomy
-    // terms and view the administrative theme.
-    $admin_user = $this->drupalCreateUser(array('administer taxonomy', 'view the administration theme'));
-    $this->drupalLogin($admin_user);
-  }
-
-  /**
-   * Test the theme used when adding, viewing and editing taxonomy terms.
-   */
-  function testTaxonomyTermThemes() {
-    // Adding a term to a vocabulary is considered an administrative action and
-    // should use the administrative theme.
-    $vocabulary = $this->createVocabulary();
-    $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add');
-    $this->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page for adding a taxonomy term."));
-
-    // Viewing a taxonomy term should use the default theme.
-    $term = $this->createTerm($vocabulary);
-    $this->drupalGet('taxonomy/term/' . $term->tid);
-    $this->assertRaw('bartik/css/style.css', t("The default theme's CSS appears on the page for viewing a taxonomy term."));
-
-    // Editing a taxonomy term should use the same theme as adding one.
-    $this->drupalGet('taxonomy/term/' . $term->tid . '/edit');
-    $this->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page for editing a taxonomy term."));
-  }
-}
