diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php b/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php
index 9a5cbde..806dc89 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php
@@ -7,9 +7,11 @@
 
 namespace Drupal\aggregator\Form;
 
-use Drupal\system\SystemConfigFormBase;
+use Drupal\Core\Form\FormInterface;
 use Drupal\Core\Config\ConfigFactory;
+use Drupal\system\SystemConfigFormBase;
 use Drupal\aggregator\Plugin\AggregatorPluginManager;
+use Drupal\Component\Utility\String;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -18,6 +20,13 @@
 class SettingsForm extends SystemConfigFormBase {
 
   /**
+   * The configuration object factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactory
+   */
+  protected $configFactory;
+
+  /**
    * The aggregator plugin managers.
    *
    * @var array
@@ -36,6 +45,13 @@ class SettingsForm extends SystemConfigFormBase {
   );
 
   /**
+   * The instantiated plugin instances.
+   *
+   * @var array
+   */
+  protected $instances = array();
+
+  /**
    * Constructs a \Drupal\aggregator\SettingsForm object.
    *
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
@@ -57,13 +73,13 @@ public function __construct(ConfigFactory $config_factory, AggregatorPluginManag
     // Get all available fetcher, parser and processor definitions.
     foreach (array('fetcher', 'parser', 'processor') as $type) {
       foreach ($this->managers[$type]->getDefinitions() as $id => $definition) {
-        $this->definitions[$type][$id] = format_string('@title <span class="description">@description</span>', array('@title' => $definition['title'], '@description' => $definition['description']));
+        $this->definitions[$type][$id] = String::format('@title <span class="description">@description</span>', array('@title' => $definition['title'], '@description' => $definition['description']));
       }
     }
   }
 
   /**
-   * Implements \Drupal\Core\ControllerInterface::create().
+   * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
     return new static(
@@ -75,14 +91,14 @@ public static function create(ContainerInterface $container) {
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::getFormID().
+   * {@inheritdoc}
    */
   public function getFormID() {
     return 'aggregator_admin_form';
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::buildForm().
+   * {@inheritdoc}
    */
   public function buildForm(array $form, array &$form_state) {
     $config = $this->configFactory->get('aggregator.settings');
@@ -136,28 +152,56 @@ public function buildForm(array $form, array &$form_state) {
       $form['basic_conf'] += $basic_conf;
     }
 
+    // Call buildForm() on the active fetcher and parser.
+    foreach (array('fetcher', 'parser') as $type) {
+      $active = $config->get($type);
+      if (array_key_exists($active, $this->definitions[$type])) {
+        $instance = $this->managers[$type]->createInstance($active);
+        if ($instance instanceof FormInterface) {
+          $form = $instance->buildForm($form, $form_state);
+          // Store the instance for validate and submit handlers.
+          $this->instances[] = $instance;
+        }
+      }
+    }
+
     // Implementing processor plugins will expect an array at $form['processors'].
     $form['processors'] = array();
-    // Call settingsForm() for each active processor.
+    // Call buildForm() for each active processor.
     foreach ($this->definitions['processor'] as $id => $definition) {
       if (in_array($id, $config->get('processors'))) {
-        $form = $this->managers['processor']->createInstance($id)->settingsForm($form, $form_state);
+        $instance = $this->managers['processor']->createInstance($id);
+        if ($instance instanceof FormInterface) {
+          $form = $instance->buildForm($form, $form_state);
+          // Store the instance for validate and submit handlers.
+          $this->instances[] = $instance;
+        }
       }
     }
     return parent::buildForm($form, $form_state);
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::submitForm().
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {
+    parent::validateForm($form, $form_state);
+    // Let active plugins validate their settings.
+    foreach ($this->instances as $instance) {
+      $instance->validateForm($form, $form_state);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function submitForm(array &$form, array &$form_state) {
     parent::submitForm($form, $form_state);
     $config = $this->configFactory->get('aggregator.settings');
-    // Let active processors save their settings.
-    foreach ($this->definitions['processor'] as $id => $definition) {
-      if (in_array($id, $config->get('processors'))) {
-        $this->managers['processor']->createInstance($id)->settingsSubmit($form, $form_state);
-      }
+
+    // Let active plugins save their settings.
+    foreach ($this->instances as $instance) {
+      $instance->submitForm($form, $form_state);
     }
 
     $config->set('items.allowed_html', $form_state['values']['aggregator_allowed_html_tags']);
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php
index 9f51a71..950eecf 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php
@@ -8,9 +8,9 @@
 namespace Drupal\aggregator\Plugin;
 
 use Drupal\Component\Plugin\PluginManagerBase;
-use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
+use Drupal\Core\Plugin\Factory\ContainerFactory;
 
 /**
  * Manages aggregator plugins.
@@ -28,6 +28,6 @@ class AggregatorPluginManager extends PluginManagerBase {
   public function __construct($type, array $namespaces) {
     $this->discovery = new AnnotatedClassDiscovery('aggregator', $type, $namespaces);
     $this->discovery = new CacheDecorator($this->discovery, "aggregator_$type:" . language(LANGUAGE_TYPE_INTERFACE)->langcode);
-    $this->factory = new DefaultFactory($this->discovery);
+    $this->factory = new ContainerFactory($this);
   }
 }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginSettingsBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginSettingsBase.php
new file mode 100644
index 0000000..d4dcf52
--- /dev/null
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginSettingsBase.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\aggregator\Plugin\AggregatorPluginSettingsBase.
+ */
+
+namespace Drupal\aggregator\Plugin;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginBase;
+use Drupal\Core\Form\FormInterface;
+
+/**
+ * Base class for aggregator's plugin implementations.
+ */
+abstract class AggregatorPluginSettingsBase extends ContainerFactoryPluginBase implements FormInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'aggregator_admin_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {
+  }
+
+}
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php
index b670383..844abb0 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php
@@ -21,31 +21,6 @@
 interface ProcessorInterface {
 
   /**
-   * Returns a form to configure settings for the processor.
-   *
-   * @param array $form
-   *   The form definition array where the settings form is being included in.
-   * @param array $form_state
-   *   An associative array containing the current state of the form.
-   *
-   * @return array
-   *   The form elements for the processor settings.
-   */
-  public function settingsForm(array $form, array &$form_state);
-
-  /**
-   * Adds processor specific submission handling for the configuration form.
-   *
-   * @param array $form
-   *   The form definition array where the settings form is being included in.
-   * @param array $form_state
-   *   An associative array containing the current state of the form.
-   *
-   * @see \Drupal\aggregator\Plugin\ProcessorInterface::settingsForm()
-   */
-  public function settingsSubmit(array $form, array &$form_state);
-
-  /**
    * Processes feed data.
    *
    * @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
index e71412b..423ed27 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
@@ -7,10 +7,12 @@
 
 namespace Drupal\aggregator\Plugin\aggregator\fetcher;
 
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\aggregator\Plugin\FetcherInterface;
 use Drupal\aggregator\Plugin\Core\Entity\Feed;
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Guzzle\Http\Client;
 use Guzzle\Http\Exception\BadResponseException;
 use Guzzle\Http\Exception\RequestException;
 
@@ -28,11 +30,31 @@
 class DefaultFetcher implements FetcherInterface {
 
   /**
-   * Implements \Drupal\aggregator\Plugin\FetcherInterface::fetch().
+   * The HTTP client to fetch the feed data with.
+   *
+   * @var \Guzzle\Http\Client
+   */
+  protected $httpClient;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static($configuration, $plugin_id, $plugin_definition, $container->get('http_default_client'));
+  }
+
+  /**
+   * Constructs a DefaultFetcher object.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, Client $http_client) {
+    $this->httpClient = $http_client;
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function fetch(Feed $feed) {
-    // @todo: Inject the http client.
-    $request = \Drupal::httpClient()->get($feed->url->value);
+    $request = $this->httpClient->get($feed->url->value);
     $feed->source_string = FALSE;
 
     // Generate conditional GET headers.
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php
index 0086bac..917d6f8 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php
@@ -7,10 +7,12 @@
 
 namespace Drupal\aggregator\Plugin\aggregator\parser;
 
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\aggregator\Plugin\ParserInterface;
 use Drupal\aggregator\Plugin\Core\Entity\Feed;
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Cache\Cache;
 
 /**
  * Defines a default parser implementation.
@@ -68,7 +70,14 @@ class DefaultParser implements ParserInterface {
   protected $item;
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ParserInterface::parse().
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static($configuration, $plugin_id, $plugin_definition);
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function parse(Feed $feed) {
     // Filter the input data.
@@ -90,7 +99,7 @@ public function parse(Feed $feed) {
       $feed->image->value = !empty($image['url']) ? $image['url'] : '';
 
       // Clear the page and block caches.
-      cache_invalidate_tags(array('content' => TRUE));
+      Cache::invalidateTags(array('content' => TRUE));
 
       return TRUE;
     }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php
index 08777d1..b527beb 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php
@@ -7,12 +7,14 @@
 
 namespace Drupal\aggregator\Plugin\aggregator\processor;
 
-use Drupal\Component\Plugin\PluginBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\aggregator\Plugin\ProcessorInterface;
+use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
 use Drupal\aggregator\Plugin\Core\Entity\Feed;
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Config\ConfigFactory;
 
 /**
  * Defines a default processor implementation.
@@ -25,13 +27,35 @@
  *   description = @Translation("Creates lightweight records from feed items.")
  * )
  */
-class DefaultProcessor extends PluginBase implements ProcessorInterface {
+class DefaultProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface {
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsForm().
+   * Contains the configuration object factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactory
+   */
+  protected $configFactory;
+
+  /**
+   * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state) {
-    $config = config('aggregator.settings');
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static($configuration, $plugin_id, $plugin_definition, $container->get('config.factory'));
+  }
+
+  /**
+   * Constructs a DefaultProcessor object.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, ConfigFactory $config) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    $config = $this->configFactory->get('aggregator.settings');
     $processors = $config->get('processors');
     $info = $this->getDefinition();
     $items = drupal_map_assoc(array(3, 5, 10, 15, 20, 25), array($this, 'formatItems'));
@@ -84,10 +108,10 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsSubmit().
+   * {@inheritdoc}
    */
-  public function settingsSubmit(array $form, array &$form_state) {
-    $config = config('aggregator.settings');
+  public function submitForm(array &$form, array &$form_state) {
+    $config = $this->configFactory->get('aggregator.settings');
     $config->set('items.expire', $form_state['values']['aggregator_clear'])
       ->set('items.teaser_length', $form_state['values']['aggregator_teaser_length'])
       ->set('source.list_max', $form_state['values']['aggregator_summary_items'])
@@ -96,7 +120,7 @@ public function settingsSubmit(array $form, array &$form_state) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::process().
+   * {@inheritdoc}
    */
   public function process(Feed $feed) {
     if (!is_array($feed->items)) {
@@ -147,7 +171,7 @@ public function process(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::remove().
+   * {@inheritdoc}
    */
   public function remove(Feed $feed) {
     $iids = Database::getConnection()->query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->id()))->fetchCol();
@@ -159,12 +183,10 @@ public function remove(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::postProcess().
-   *
-   * Expires items from a feed depending on expiration settings.
+   * {@inheritdoc}
    */
   public function postProcess(Feed $feed) {
-    $aggregator_clear = config('aggregator.settings')->get('items.expire');
+    $aggregator_clear = $this->configFactory->get('aggregator.settings')->get('items.expire');
 
     if ($aggregator_clear != AGGREGATOR_CLEAR_NEVER) {
       // Remove all items that are older than flush item timer.
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
index ca56e20..6367b62 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
@@ -335,17 +335,17 @@ function getEmptyOpml() {
   }
 
   function getRSS091Sample() {
-    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
+    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_rss091.xml';
   }
 
   function getAtomSample() {
     // The content of this sample ATOM feed is based directly off of the
     // example provided in RFC 4287.
-    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_atom.xml';
+    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_atom.xml';
   }
 
   function getHtmlEntitiesSample() {
-    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_title_entities.xml';
+    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_title_entities.xml';
   }
 
   /**
diff --git a/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php b/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php
new file mode 100644
index 0000000..2ad2610
--- /dev/null
+++ b/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\aggregator\Tests\Plugin\AggregatorPluginSettingsBaseTest
+ */
+
+namespace Drupal\aggregator\Tests\Plugin;
+
+use Drupal\Tests\UnitTestCase;
+use Drupal\aggregator\Form\SettingsForm;
+
+/**
+ * Tests plugins settings on aggregator plugins.
+ *
+ * @group Aggregator
+ */
+class AggregatorPluginSettingsBaseTest extends UnitTestCase {
+
+  /**
+   * The aggregator settings form object under test.
+   *
+   * @var \Drupal\aggregator\Form\SettingsForm
+   */
+  protected $settingsForm;
+
+  /**
+   * The stubbed config factory object.
+   *
+   * @var \PHPUnit_Framework_MockObject_MockBuilder
+   */
+  protected $configFactory;
+
+  /**
+   * The stubbed aggregator plugin managers array.
+   *
+   * @var array
+   */
+  protected $managers;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Aggregator plugin settings tests',
+      'description' => 'Test settings configuration of individual aggregator plugins.',
+      'group' => 'Aggregator',
+    );
+  }
+
+  public function setUp() {
+    $this->configFactory = $this->getConfigFactoryStub(
+      array(
+        'aggregator.settings' => array(
+          'processors' => array('aggregator_test'),
+        ),
+        'aggregator_test.settings' => array(),
+      )
+    );
+    foreach (array('fetcher', 'parser', 'processor') as $type) {
+      $this->managers[$type] = $this->getMockBuilder('Drupal\aggregator\Plugin\AggregatorPluginManager')
+        ->disableOriginalConstructor()
+        ->getMock();
+      $this->managers[$type]->expects($this->once())
+        ->method('getDefinitions')
+        ->will($this->returnValue(array('aggregator_test' => array('title' => '', 'description' => ''))));
+    }
+    $this->settingsForm = new SettingsForm($this->configFactory, $this->managers['fetcher'], $this->managers['parser'], $this->managers['processor']);
+  }
+
+  /**
+   * Test for AggregatorPluginSettingsBase.
+   *
+   * Ensure that the settings form calls build, validate and submit methods on
+   * plugins that extend AggregatorPluginSettingsBase.
+   */
+  public function testSettingsForm() {
+    $form_state = array();
+    $test_processor = $this->getMock(
+      'Drupal\aggregator_test\Plugin\aggregator\processor\TestProcessor',
+      array('buildForm', 'validateForm', 'submitForm'),
+      array(array(), 'aggregator_test', array(), $this->configFactory)
+    );
+    $test_processor->expects($this->at(0))
+      ->method('buildForm')
+      ->with($this->anything(), $form_state)
+      ->will($this->returnArgument(0));
+    $test_processor->expects($this->at(1))
+      ->method('validateForm')
+      ->with($this->anything(), $form_state);
+    // @todo Restore when we get rid of drupal_set_message().
+    /*$test_processor->expects($this->at(2))
+      ->method('submitForm')
+      ->with($this->anything(), $form_state);*/
+    $this->managers['processor']->expects($this->once())
+      ->method('createInstance')
+      ->with($this->equalTo('aggregator_test'))
+      ->will($this->returnValue($test_processor));
+    $form = $this->settingsForm->buildForm(array(), $form_state);
+    $this->settingsForm->validateForm($form, $form_state);
+    // @todo Restore when we get rid of drupal_set_message().
+    //$this->settingsForm->submitForm($form, $form_state);
+  }
+
+}
diff --git a/core/modules/aggregator/tests/aggregator_test.info.yml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.info.yml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test.info.yml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.info.yml
diff --git a/core/modules/aggregator/tests/aggregator_test.module b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.module
similarity index 97%
rename from core/modules/aggregator/tests/aggregator_test.module
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.module
index 09190fa..2613d58 100644
--- a/core/modules/aggregator/tests/aggregator_test.module
+++ b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.module
@@ -56,7 +56,7 @@ function aggregator_test_feed($use_last_modified = FALSE, $use_etag = FALSE) {
   drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8');
 
   // Read actual feed from file.
-  $file_name = DRUPAL_ROOT . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
+  $file_name = DRUPAL_ROOT . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_rss091.xml';
   $handle = fopen($file_name, 'r');
   $feed = fread($handle, filesize($file_name));
   fclose($handle);
diff --git a/core/modules/aggregator/tests/aggregator_test_atom.xml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_atom.xml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test_atom.xml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_atom.xml
diff --git a/core/modules/aggregator/tests/aggregator_test_rss091.xml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_rss091.xml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test_rss091.xml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_rss091.xml
diff --git a/core/modules/aggregator/tests/aggregator_test_title_entities.xml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_title_entities.xml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test_title_entities.xml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_title_entities.xml
diff --git a/core/modules/aggregator/tests/config/aggregator_test.settings.yml b/core/modules/aggregator/tests/modules/aggregator_test/config/aggregator_test.settings.yml
similarity index 100%
rename from core/modules/aggregator/tests/config/aggregator_test.settings.yml
rename to core/modules/aggregator/tests/modules/aggregator_test/config/aggregator_test.settings.yml
diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php
similarity index 100%
rename from core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php
rename to core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php
diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php
similarity index 100%
rename from core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php
rename to core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php
diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
similarity index 55%
rename from core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
rename to core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
index 3ffe213..7e35b85 100644
--- a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
+++ b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
@@ -7,11 +7,13 @@
 
 namespace Drupal\aggregator_test\Plugin\aggregator\processor;
 
-use Drupal\Component\Plugin\PluginBase;
 use Drupal\aggregator\Plugin\ProcessorInterface;
 use Drupal\aggregator\Plugin\Core\Entity\Feed;
+use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Config\ConfigFactory;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines a default processor implementation.
@@ -24,14 +26,35 @@
  *   description = @Translation("Test generic processor functionality.")
  * )
  */
-class TestProcessor extends PluginBase implements ProcessorInterface {
+class TestProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface {
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsForm().
+   * Contains the configuration object factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactory
    */
-  public function settingsForm(array $form, array &$form_state) {
-    $config = config('aggregator.settings');
-    $processors = $config->get('processors');
+  protected $configFactory;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static($configuration, $plugin_id, $plugin_definition, $container->get('config.factory'));
+  }
+
+  /**
+   * Constructs a DefaultProcessor object.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, ConfigFactory $config) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    $processors = $this->configFactory->get('aggregator.settings')->get('processors');
     $info = $this->getDefinition();
 
     $form['processors'][$info['id']] = array(
@@ -46,22 +69,22 @@ public function settingsForm(array $form, array &$form_state) {
       '#type' => 'number',
       '#min' => 1,
       '#max' => 1000,
-      '#default_value' => config('aggregator_test.settings')->get('items.dummy_length'),
+      '#default_value' => $this->configFactory->get('aggregator_test.settings')->get('items.dummy_length'),
     );
     return $form;
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsSubmit().
+   * {@inheritdoc}
    */
-  public function settingsSubmit(array $form, array &$form_state) {
-    config('aggregator_test.settings')
+  public function submitForm(array &$form, array &$form_state) {
+    $this->configFactory->get('aggregator_test.settings')
       ->set('items.dummy_length', $form_state['values']['dummy_length'])
       ->save();
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::process().
+   * {@inheritdoc}
    */
   public function process(Feed $feed) {
     foreach ($feed->items as &$item) {
@@ -71,7 +94,7 @@ public function process(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::remove().
+   * {@inheritdoc}
    */
   public function remove(Feed $feed) {
     // Append a random number, just to change the feed description.
@@ -79,7 +102,7 @@ public function remove(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::postProcess().
+   * {@inheritdoc}
    */
   public function postProcess(Feed $feed) {
     // Double the refresh rate.
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index 7f8441e..e27c950 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -8,8 +8,21 @@
 
 foreach (scandir(__DIR__ . "/../modules") as $module) {
   $loader->add('Drupal\\' . $module, __DIR__ . "/../modules/" . $module . "/lib");
+  // @todo This is what http://drupal.org/node/1974266 does.RTBC!
+  // Add test module classes.
+  $test_modules_dir = __DIR__ . "/../modules/$module/tests/modules";
+  if (is_dir($test_modules_dir)) {
+    foreach (scandir($test_modules_dir) as $test_module) {
+      $loader->add('Drupal\\' . $module, $test_modules_dir . '/' . $test_module . "/lib");
+    }
+  }
 }
 
 require __DIR__ . "/../../core/lib/Drupal.php";
-// Look into removing this later.
+// @todo Look into removing this later.
 define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']);
+
+// @todo Get rid once http://drupal.org/node/1813762 is in.
+function t($string) {
+  return $string;
+}
