diff --git a/lib/Drupal/views/Tests/Plugin/FilterTest.php b/lib/Drupal/views/Tests/Plugin/FilterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..08ed20f8f59f16c8a2e8d95c0a5842a9ce82542b
--- /dev/null
+++ b/lib/Drupal/views/Tests/Plugin/FilterTest.php
@@ -0,0 +1,144 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views\Tests\Plugin\FilterTest.
+ */
+
+namespace Drupal\views\Tests\Plugin;
+
+use Drupal\views_test_data\Plugin\views\filter\FilterTest as FilterPlugin;
+
+/**
+ * Tests general filter plugin functionality.
+ *
+ * @see Drupal\views\Plugin\views\filter\FilterPluginBase
+ */
+class FilterTest extends PluginTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('views_ui');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Filter: General',
+      'description' => 'Tests general filter plugin functionality.',
+      'group' => 'Views Plugins',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+
+    $this->enableViewsTestModule();
+  }
+
+  /**
+   * Overrides Drupal\views\Tests\ViewTestBase::viewsData().
+   */
+  protected function viewsData() {
+    $data = parent::viewsData();
+    $data['views_test']['name']['filter']['id'] = 'test_filter';
+
+    return $data;
+  }
+
+  /**
+   * Test query of the row plugin.
+   */
+  public function testFilterQuery() {
+    // Check that we can find the test filter plugin.
+    $plugin = views_get_plugin('filter', 'test_filter');
+    $this->assertTrue($plugin instanceof FilterPlugin, 'Test filter plugin found.');
+
+    $view = views_get_view('test_filter');
+    $view->initDisplay();
+
+    // Change the filtering.
+    $view->display['default']->handler->overrideOption('filters', array(
+      'test_filter' => array(
+        'id' => 'test_filter',
+        'table' => 'views_test',
+        'field' => 'name',
+        'operator' => '=',
+        'value' => 'John',
+        'group' => 0,
+      ),
+    ));
+
+    $this->executeView($view);
+
+    // Make sure the query have where data.
+    $this->assertTrue(!empty($view->query->where));
+
+    // Check the data added.
+    $where = $view->query->where;
+    $this->assertIdentical($where[0]['conditions'][0]['field'], 'views_test.name', 'Where condition field matches');
+    $this->assertIdentical($where[0]['conditions'][0]['value'], 'John', 'Where condition value matches');
+    $this->assertIdentical($where[0]['conditions'][0]['operator'], '=', 'Where condition operator matches');
+
+    $this->executeView($view);
+
+    // Check that our operator and value match on the filter.
+    $this->assertIdentical($view->filter['test_filter']->operator, '=');
+    $this->assertIdentical($view->filter['test_filter']->value, 'John');
+
+    // Check that we have some results.
+    $this->assertEqual(count($view->result), 1, format_string('Results were returned. @count results.', array('@count' => count($view->result))));
+
+    $view->destroy();
+
+    $view->initDisplay();
+
+    // Change the filtering.
+    $view->display['default']->handler->overrideOption('filters', array(
+      'test_filter' => array(
+        'id' => 'test_filter',
+        'table' => 'views_test',
+        'field' => 'name',
+        'operator' => '<>',
+        'value' => 'John',
+        'group' => 0,
+      ),
+    ));
+
+    $this->executeView($view);
+
+    // Check that our operator and value match on the filter.
+    $this->assertIdentical($view->filter['test_filter']->operator, '<>');
+    $this->assertIdentical($view->filter['test_filter']->value, 'John');
+
+    // Test that no nodes have been returned (Only 'page' type nodes should
+    // exist).
+    $this->assertEqual(count($view->result), 4, format_string('No results were returned. @count results.', array('@count' => count($view->result))));
+
+    $view->destroy();
+    $view->initDisplay();
+
+    // Set the test_enable option to FALSE. The 'where' clause should not be
+    // added to the query.
+    $view->display['default']->handler->overrideOption('filters', array(
+      'test_filter' => array(
+        'id' => 'test_filter',
+        'table' => 'views_test',
+        'field' => 'name',
+        'operator' => '<>',
+        'value' => 'John',
+        'group' => 0,
+        // Disable this option, so nothing should be added to the query.
+        'test_enable' => FALSE,
+      ),
+    ));
+
+    // Execute the view again.
+    $this->executeView($view);
+
+    // Check if we have all 5 results.
+    $this->assertEqual(count($view->result), 5, format_string('All @count results returned', array('@count' => count($view->display))));
+  }
+
+}
diff --git a/tests/views_test_data/config/views.view.test_filter.yml b/tests/views_test_data/config/views.view.test_filter.yml
new file mode 100644
index 0000000000000000000000000000000000000000..553a496d3a8d1d01b385f62ee26d0f002ff32313
--- /dev/null
+++ b/tests/views_test_data/config/views.view.test_filter.yml
@@ -0,0 +1,38 @@
+api_version: '3.0'
+base_table: views_test
+core: 8
+disabled: false
+display:
+  default:
+    display_options:
+      access:
+        type: perm
+      cache:
+        type: none
+      exposed_form:
+        type: basic
+      fields:
+        title:
+          alter:
+            ellipsis: '0'
+            word_boundary: '0'
+          field: name
+          id: name
+          label: ''
+          table: views_test
+      filters:
+        type:
+          field: name
+          id: test_filter
+          table: views_test
+      query:
+        type: views_query
+      row_plugin: fields
+      style_plugin: default
+      use_more_always: '0'
+    display_plugin: default
+    display_title: Master
+    id: default
+    position: '0'
+human_name: 'Test filters'
+name: test_filter
diff --git a/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/filter/FilterTest.php b/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/filter/FilterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa92dc298c582d5115368ec56ca986bb8de6d09e
--- /dev/null
+++ b/tests/views_test_data/lib/Drupal/views_test_data/Plugin/views/filter/FilterTest.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views_test_data\Plugin\views\filter\FilterTest.
+ */
+
+namespace Drupal\views_test_data\Plugin\views\filter;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+use Drupal\views\Plugin\views\filter\FilterPluginBase;
+
+/**
+ * @Plugin(
+ *   id = "test_filter",
+ *   title = @Translation("Test filter plugin"),
+ *   help = @Translation("Provides a generic filter test plugin."),
+ *   base = "node",
+ *   type = "type"
+ * )
+ */
+class FilterTest extends FilterPluginBase {
+
+  /**
+   * Overrides Drupal\views\Plugin\views\row\RowPluginBase::defineOptions().
+   *
+   * @return array
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+
+    $options['test_enable'] = array('default' => TRUE, 'bool' => TRUE);
+    return $options;
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\row\RowPluginBase::buildOptionsForm().
+   *
+   * @return array
+   */
+  public function buildOptionsForm(&$form, &$form_state) {
+    parent::buildOptionsForm($form, $form_state);
+
+    $form['test_enable'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Controls whether the filter plugin should be active.'),
+      '#default_value' => $this->options['test_enable'],
+    );
+  }
+
+  /**
+   * Overrides Drupal\views\Plugin\views\filter\FilterPluginBase::query().
+   */
+  public function query() {
+    // Call the parent if this option is enabled.
+    if ($this->options['test_enable']) {
+      parent::query();
+    }
+  }
+
+}