diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
index 2dd7ace..b2a94b0 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
@@ -428,7 +428,7 @@ protected function invokeHook($hook, EntityInterface $entity) {
    * Implements Drupal\Core\Entity\EntityStorageControllerInterface::getQueryServicename().
    */
   public function getQueryServicename() {
-    throw new \LogicException('Querying configuration entities is not supported.');
+    return 'entity.query.config';
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Condition.php b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php
new file mode 100644
index 0000000..b7abed8
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php
@@ -0,0 +1,175 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\Entity\Query\Condition.
+ */
+
+namespace Drupal\Core\Config\Entity\Query;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Entity\Query\ConditionBase;
+use Drupal\Core\Entity\Query\ConditionInterface;
+
+class Condition extends ConditionBase {
+
+  /**
+   * Implements \Drupal\Core\Entity\Query\ConditionInterface::compile().
+   */
+  public function compile($configs) {
+    $and = strtoupper($this->conjunction) == 'AND';
+    $simple_conditions = array();
+    $complex_conditions = array();
+    foreach ($this->conditions as $condition) {
+      if ($condition['field'] instanceOf ConditionInterface) {
+        // Complex conditions contain a group of conditions and are handled
+        // by recursive calls.
+        $complex_conditions[] = $condition;
+      }
+      else {
+        // Simple conditions just contain a field, a value and an operator and
+        // handled without an extra function call.
+        // The field might contain a wildcard.
+        $condition['wildcard'] = strpos($condition['field'], '*') !== FALSE;
+        $simple_conditions[] = $condition;
+      }
+    }
+    $return = array();
+    if ($simple_conditions) {
+      foreach ($configs as $config_name => $config) {
+        foreach ($simple_conditions as &$condition) {
+          if (!isset($condition['operator'])) {
+            $condition['operator'] = is_array($condition['value']) ? 'IN' : '=';
+          }
+          if ($condition['wildcard']) {
+            $match = $this->matchWildcard($condition, $config, explode('.', $condition['field']));
+          }
+          else {
+            $key = $condition['field'];
+            $match = $this->match($condition, isset($config[$key]) ? $config[$key] : NULL);
+          }
+          // If AND and it's not matching, then the rest of conditions do not
+          // matter and this config object does not match.
+          // If OR and it is matching, then the rest of conditions do not
+          // matter and this config object does match.
+          if ($and != $match ) {
+            break;
+          }
+        }
+        if ($match) {
+          $return[$config_name] = $config;
+        }
+      }
+    }
+    elseif (!$complex_conditions || $and) {
+      // If there were no simple conditions then either:
+      // - Complex conditions, OR: need to start from no entities.
+      // - Complex conditions, AND: need to start from all entities.
+      // - No complex conditions (AND/OR doesn't matter): need to return all
+      //   entities.
+      $return = $configs;
+    }
+    foreach ($complex_conditions as $condition) {
+      $group_entities = $condition['field']->compile($configs);
+      if ($and) {
+        $return = array_intersect_key($return, $group_entities);
+      }
+      else {
+        $return = $return + $group_entities;
+      }
+    }
+
+    return $return;
+  }
+
+  /**
+   * Do the actual matching.
+   *
+   * @param $condition
+   *   The condition array as created by the condition() method.
+   * @param $value
+   *   The value to match against.
+   * @return bool
+   *   TRUE when matches.
+   */
+  function match($condition, $value) {
+    if (isset($value)) {
+      switch ($condition['operator']) {
+        case '=':
+          return $value == $condition['value'];
+        case '>':
+          return $value > $condition['value'];
+        case '<':
+          return $value < $condition['value'];
+        case '>=':
+          return $value >= $condition['value'];
+        case '<=':
+          return $value <= $condition['value'];
+        case 'IN':
+          return array_search($value, $condition['value']) !== FALSE;
+        case 'NOT IN':
+          return array_search($value, $condition['value']) === FALSE;
+        case 'STARTS_WITH':
+          return strpos($value, $condition['value']) === 0;
+        case 'CONTAINS':
+          return strpos($value, $condition['value']) !== FALSE;
+        case 'ENDS_WITH':
+          return substr($value, -strlen($condition['value'])) === (string) $condition['value'];
+        case 'IS NOT NULL':
+          return TRUE;
+      }
+    }
+    return $condition['operator'] === 'IS NULL';
+  }
+
+  /**
+   * Implements \Drupal\Core\Entity\Query\ConditionInterface::exists().
+   */
+  public function exists($field, $langcode = NULL) {
+    return $this->condition($field, NULL, 'IS NOT NULL', $langcode);
+  }
+
+  /**
+   * Implements \Drupal\Core\Entity\Query\ConditionInterface::notExists().
+   */
+  public function notExists($field, $langcode = NULL) {
+    return $this->condition($field, NULL, 'IS NULL', $langcode);
+  }
+
+  /**
+   * Match when the condition field contains a wildcard.
+   *
+   * @param $condition
+   *   The condition array as created by the condition() method.
+   * @param array $data
+   *   The config array or part of it.
+   * @param array $needs_matching
+   *   The list of config array keys needing a match.
+   * @param array $parents
+   *   The current list of parents.
+   * @return bool
+   *   TRUE when matched.
+   */
+  function matchWildcard($condition, array $data, array $needs_matching, array $parents = array()) {
+    $parent = array_shift($needs_matching);
+    $candidates = array();
+    if ($parent === '*') {
+      $candidates = array_keys($data);
+    }
+    elseif (isset($data[$parent])) {
+      $candidates = array($parent);
+    }
+    foreach ($candidates as $key) {
+      $new_parents = $parents;
+      $new_parents[] = $key;
+      if (is_array($data[$key]) && $needs_matching) {
+        return $this->matchWildcard($condition, $data[$key], $needs_matching, $new_parents);
+      }
+      elseif ($this->match($condition, $data[$key])) {
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Query.php b/core/lib/Drupal/Core/Config/Entity/Query/Query.php
new file mode 100644
index 0000000..ade7f4c
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/Query/Query.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\Entity\Query\Query.
+ */
+
+namespace Drupal\Core\Config\Entity\Query;
+
+use Drupal\Core\Config\StorageInterface;
+use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Entity\Query\QueryBase;
+
+/**
+ * Defines the entity query for configuration entities.
+ */
+class Query extends QueryBase {
+
+  /**
+   * Stores the entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManager
+   */
+  protected $entityManager;
+
+  /**
+   * The config storage used by the config entity query.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $configStorage;
+
+  /**
+   * Constructs a Query object.
+   */
+  function __construct($entity_type, $conjunction, EntityManager $entity_manager, StorageInterface $config_storage) {
+    parent::__construct($entity_type, $conjunction);
+    $this->entityManager = $entity_manager;
+    $this->configStorage = $config_storage;
+  }
+
+  /**
+   * Implements \Drupal\Core\Entity\Query\QueryInterface::conditionGroupFactory().
+   */
+  public function conditionGroupFactory($conjunction = 'AND') {
+    return new Condition($conjunction);
+  }
+
+  /**
+   * Implements \Drupal\Core\Entity\Query\QueryInterface::execute().
+   */
+  public function execute() {
+    // Load all config files.
+    $entity_info = $this->entityManager->getDefinition($this->getEntityType());
+    $prefix = $entity_info['config_prefix'];
+
+    $names = $this->configStorage->listAll($prefix);
+    $configs = array();
+    foreach ($names as $name) {
+      $configs[$name] = config($name)->get();
+    }
+    $result = $this->condition->compile($configs);
+
+    // Apply sort settings.
+    foreach ($this->sort as $property => $sort) {
+      $direction = $sort['direction'] == 'ASC' ? -1 : 1;
+      uasort($result, function($a, $b) use ($property, $direction) {
+        return ($a[$property] <= $b[$property]) ? $direction : -$direction;
+      });
+    }
+
+    // Let the pager do its work.
+    $this->initializePager();
+
+    if ($this->range) {
+      $result = array_slice($result, $this->range['start'], $this->range['length'], TRUE);
+    }
+    if ($this->count) {
+      return count($result);
+    }
+
+    $return = array();
+    $prefix_length = strlen($prefix) + 1;
+    foreach ($result as $config_name => $data) {
+      $id = substr($config_name, $prefix_length);
+      $return[$id] = $id;
+    }
+    return $return;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/QueryFactory.php b/core/lib/Drupal/Core/Config/Entity/Query/QueryFactory.php
new file mode 100644
index 0000000..fe93713
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/Query/QueryFactory.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\Entity\Query\QueryFactory.
+ */
+
+namespace Drupal\Core\Config\Entity\Query;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Config\StorageInterface;
+use Drupal\Core\Entity\EntityManager;
+
+/**
+ * Provides a factory for creating entity query objects for the config backend.
+ */
+class QueryFactory {
+
+  /**
+   * The config storage used by the config entity query.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $configStorage;
+
+  /**
+   * Constructs a QueryFactory object.
+   *
+   * @param \Drupal\Core\Config\StorageInterface $config_storage
+   *   The config storage used by the config entity query.
+   */
+  public function __construct(StorageInterface $config_storage) {
+    return $this->configStorage = $config_storage;
+  }
+
+  /**
+   * Instantiate a entity query for a certain entity type.
+   *
+   * @param string $entity_type
+   *   The entity type for the query.
+   * @param string $conjunction
+   *   The operator to use to combine conditions: 'AND' or 'OR'.
+   * @param \Drupal\Core\Entity\EntityManager $entity_manager
+   *   The entity manager that handles the entity type.
+   *
+   * @return \Drupal\Core\Config\Entity\Query\Query
+   *   An entity query for a specific configuration entity type.
+   */
+  public function get($entity_type, $conjunction, EntityManager $entity_manager) {
+    return new Query($entity_type, $conjunction, $entity_manager, $this->configStorage);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index bc6afef..0729c64 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -155,9 +155,12 @@ public function build(ContainerBuilder $container) {
     $this->registerTwig($container);
     $this->registerRouting($container);
 
-    // Add the entity query factory.
+    // Add the entity query factories.
     $container->register('entity.query', 'Drupal\Core\Entity\Query\QueryFactory')
-      ->addArgument(new Reference('service_container'));
+      ->addArgument(new Reference('plugin.manager.entity'))
+      ->addMethodCall('setContainer', array(new Reference('service_container')));
+    $container->register('entity.query.config', 'Drupal\Core\Config\Entity\Query\QueryFactory')
+      ->addArgument(new Reference('config.storage'));
 
     $container->register('router.dumper', 'Drupal\Core\Routing\MatcherDumper')
       ->addArgument(new Reference('database'));
diff --git a/core/lib/Drupal/Core/Entity/Query/QueryFactory.php b/core/lib/Drupal/Core/Entity/Query/QueryFactory.php
index d9b57bc..22c7799 100644
--- a/core/lib/Drupal/Core/Entity/Query/QueryFactory.php
+++ b/core/lib/Drupal/Core/Entity/Query/QueryFactory.php
@@ -7,24 +7,24 @@
 
 namespace Drupal\Core\Entity\Query;
 
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Entity\EntityManager;
+use Symfony\Component\DependencyInjection\ContainerAware;
 
 /**
  * Factory class Creating entity query objects.
  */
-class QueryFactory {
+class QueryFactory extends ContainerAware {
 
   /**
-   * var \Symfony\Component\DependencyInjection\ContainerInterface
+   * @var \Drupal\Core\Entity\EntityManager
    */
-  protected $container;
-
+  protected $entityManager;
 
   /**
-   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+   * @param \Drupal\Core\Entity\EntityManager $entity_manager
    */
-  function __construct(ContainerInterface $container) {
-    $this->container = $container;
+  public function __construct(EntityManager $entity_manager) {
+    $this->entityManager = $entity_manager;
   }
 
   /**
@@ -33,8 +33,8 @@ function __construct(ContainerInterface $container) {
    * @return QueryInterface
    */
   public function get($entity_type, $conjunction = 'AND') {
-    $service_name = drupal_container()->get('plugin.manager.entity')->getStorageController($entity_type)->getQueryServicename();
-    return $this->container->get($service_name)->get($entity_type, $conjunction);
+    $service_name = $this->entityManager->getStorageController($entity_type)->getQueryServicename();
+    return $this->container->get($service_name)->get($entity_type, $conjunction, $this->entityManager);
   }
 
 }
diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Core/Entity/ConfigQueryTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Core/Entity/ConfigQueryTest.php
new file mode 100644
index 0000000..c1f6b8e
--- /dev/null
+++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Core/Entity/ConfigQueryTest.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\config_test\Plugin\Core\Entity\ConfigQueryTest.
+ */
+
+namespace Drupal\config_test\Plugin\Core\Entity;
+
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Defines the ConfigQueryTest configuration entity used by the query test.
+ *
+ * @Plugin(
+ *   id = "config_query_test",
+ *   label = @Translation("Test configuration for query"),
+ *   module = "config_test",
+ *   controller_class = "Drupal\config_test\ConfigTestStorageController",
+ *   list_controller_class = "Drupal\Core\Config\Entity\ConfigEntityListController",
+ *   form_controller_class = {
+ *     "default" = "Drupal\config_test\ConfigTestFormController"
+ *   },
+ *   uri_callback = "config_test_uri",
+ *   config_prefix = "config_query_test.dynamic",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ *
+ *  @see \Drupal\entity\Tests\ConfigEntityQueryTest
+ */
+class ConfigQueryTest extends ConfigTest {
+
+  /**
+   * A number used by the sort tests.
+   */
+  public $number;
+
+  /**
+   * An array used by the wildcard tests.
+   */
+  public $array;
+}
diff --git a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php
index 7f78e87..41091a6 100644
--- a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php
+++ b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php
@@ -46,6 +46,7 @@ public function conditionGroupFactory($conjunction = 'AND') {
    */
   public function execute() {
     $entity_type = $this->entityType;
+    // @todo change to a method call once http://drupal.org/node/1892462 is in.
     $entity_info = entity_get_info($entity_type);
     if (!isset($entity_info['base_table'])) {
       throw new QueryException("No base table, invalid query.");
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/ConfigEntityQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/ConfigEntityQueryTest.php
new file mode 100644
index 0000000..305f954
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/ConfigEntityQueryTest.php
@@ -0,0 +1,435 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\ConfigEntityQueryTest.
+ */
+
+namespace Drupal\system\Tests\Entity;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+
+/**
+ * Tests the config entity query.
+ *
+ * @see \Drupal\Core\entity\Query
+ */
+class ConfigEntityQueryTest extends DrupalUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('config_test');
+
+  /**
+   * Stores the search results for alter comparision.
+   *
+   * @var array
+   */
+  protected $queryResults;
+
+  /**
+   * The query factory used to construct all queries in the test.
+   *
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  protected $factory;
+
+  /**
+   * Stores all config entities created for the test.
+   *
+   * @var array
+   */
+  protected $entities;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Config Entity Query',
+      'description' => 'Tests Config Entity Query functionality.',
+      'group' => 'Configuration',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+   $this->entities = array();
+    $this->enableModules(array('entity'), TRUE);
+    $this->factory = $this->container->get('entity.query');
+
+    $array['level1']['level2']['level3'] = 1;
+    $entity = entity_create('config_query_test', array(
+      'label' => $this->randomName(),
+      'id' => '1',
+      'number' => 31,
+      'array' => $array,
+    ));
+    $this->entities[] = $entity;
+    $entity->enforceIsNew();
+    $entity->save();
+
+    $array['level1']['level2']['level3'] = 2;
+    $entity = entity_create('config_query_test', array(
+      'label' => $this->randomName(),
+      'id' => '2',
+      'number' => 41,
+      'array' => $array,
+    ));
+    $this->entities[] = $entity;
+    $entity->enforceIsNew();
+    $entity->save();
+
+    $array['level1']['level2']['level3'] = 1;
+    $entity = entity_create('config_query_test', array(
+      'label' => 'test_prefix_' . $this->randomName(),
+      'id' => '3',
+      'number' => 59,
+      'array' => $array,
+    ));
+    $this->entities[] = $entity;
+    $entity->enforceIsNew();
+    $entity->save();
+
+    $array['level1']['level2']['level3'] = 2;
+    $entity = entity_create('config_query_test', array(
+      'label' => $this->randomName() . '_test_suffix',
+      'id' => '4',
+      'number' => 26,
+      'array' => $array,
+    ));
+    $this->entities[] = $entity;
+    $entity->enforceIsNew();
+    $entity->save();
+
+    $array['level1']['level2']['level3'] = 3;
+    $entity = entity_create('config_query_test', array(
+      'label' => $this->randomName() . '_test_contains_' . $this->randomName(),
+      'id' => '5',
+      'number' => 53,
+      'array' => $array,
+    ));
+    $this->entities[] = $entity;
+    $entity->enforceIsNew();
+    $entity->save();
+  }
+
+  /**
+   * Test basic functionality.
+   */
+  public function testConfigEntityQuery() {
+    // Run a test without any condition.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->execute();
+    $this->assertResults(array('1', '2', '3', '4', '5'));
+    // No conditions, OR.
+    $this->queryResults = $this->factory->get('config_query_test', 'OR')
+      ->execute();
+    $this->assertResults(array('1', '2', '3', '4', '5'));
+
+    // Filter by ID with equality.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '3')
+      ->execute();
+    $this->assertResults(array('3'));
+
+    // Filter by label with a known prefix.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('label', 'test_prefix', 'STARTS_WITH')
+      ->execute();
+    $this->assertResults(array('3'));
+
+    // Filter by label with a known suffix.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('label', 'test_suffix', 'ENDS_WITH')
+      ->execute();
+    $this->assertResults(array('4'));
+
+    // Filter by label with a known containing word.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('label', 'test_contains', 'CONTAINS')
+      ->execute();
+    $this->assertResults(array('5'));
+
+    // Filter by ID with the IN operator.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', array('2', '3'), 'IN')
+      ->execute();
+    $this->assertResults(array('2', '3'));
+
+    // Filter by ID with the implicit IN operator.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', array('2', '3'))
+      ->execute();
+    $this->assertResults(array('2', '3'));
+
+    // Filter by ID with the > operator.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '3', '>')
+      ->execute();
+    $this->assertResults(array('4', '5'));
+
+    // Filter by ID with the >= operator.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '3', '>=')
+      ->execute();
+    $this->assertResults(array('3', '4', '5'));
+
+    // Filter by ID with the < operator.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '3', '<')
+      ->execute();
+    $this->assertResults(array('1', '2'));
+
+    // Filter by ID with the <= operator.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '3', '<=')
+      ->execute();
+    $this->assertResults(array('1', '2', '3'));
+
+    // Filter by two conditions on the same field.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('label', 'test_pref', 'STARTS_WITH')
+      ->condition('label', 'test_prefix', 'STARTS_WITH')
+      ->execute();
+    $this->assertResults(array('3'));
+
+    // Filter by two conditions on different fields. The first query matches for
+    // a different ID, so the result is empty.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('label', 'test_prefix', 'STARTS_WITH')
+      ->condition('id', '5')
+      ->execute();
+    $this->assertResults(array());
+
+    // Filter by two different conditions on different fields. This time the
+    // first condition matches on one item, but the second one does as well.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('label', 'test_prefix', 'STARTS_WITH')
+      ->condition('id', '3')
+      ->execute();
+    $this->assertResults(array('3'));
+
+    // Filter by two different conditions, of which the first one matches for
+    // every entry, the second one as well, but just the third one filters so
+    // that just two are left.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '1', '>=')
+      ->condition('number', 10, '>=')
+      ->condition('number', 50, '>=')
+      ->execute();
+    $this->assertResults(array('3', '5'));
+
+    // Filter with an OR condition group.
+    $this->queryResults = $this->factory->get('config_query_test', 'OR')
+      ->condition('id', 1)
+      ->condition('id', '2')
+      ->execute();
+    $this->assertResults(array('1', '2'));
+
+    // Simplify it with IN.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', array('1', '2'))
+      ->execute();
+    $this->assertResults(array('1', '2'));
+    // Try explicit IN.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', array('1', '2'), 'IN')
+      ->execute();
+    $this->assertResults(array('1', '2'));
+    // Try not IN.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', array('1', '2'), 'NOT IN')
+      ->execute();
+    $this->assertResults(array('3', '4', '5'));
+
+    // Filter with an OR condition group on different fields.
+    $this->queryResults = $this->factory->get('config_query_test', 'OR')
+      ->condition('id', 1)
+      ->condition('number', 41)
+      ->execute();
+    $this->assertResults(array('1', '2'));
+
+    // Filter with an OR condition group on different fields but matching on the
+    // same entity.
+    $this->queryResults = $this->factory->get('config_query_test', 'OR')
+      ->condition('id', 1)
+      ->condition('number', 31)
+      ->execute();
+    $this->assertResults(array('1'));
+
+    // NO simple conditions, YES complex conditions, 'AND'.
+    $query = $this->factory->get('config_query_test', 'AND');
+    $and_condition_1 = $query->orConditionGroup()
+      ->condition('id', '2')
+      ->condition('label', $this->entities[0]->label);
+    $and_condition_2 = $query->orConditionGroup()
+      ->condition('id', 1)
+      ->condition('label', $this->entities[3]->label);
+    $this->queryResults = $query
+      ->condition($and_condition_1)
+      ->condition($and_condition_2)
+      ->execute();
+    $this->assertResults(array('1'));
+
+    // NO simple conditions, YES complex conditions, 'OR'.
+    $query = $this->factory->get('config_query_test', 'OR');
+    $and_condition_1 = $query->andConditionGroup()
+      ->condition('id', 1)
+      ->condition('label', $this->entities[0]->label);
+    $and_condition_2 = $query->andConditionGroup()
+      ->condition('id', '2')
+      ->condition('label', $this->entities[1]->label);
+    $this->queryResults = $query
+      ->condition($and_condition_1)
+      ->condition($and_condition_2)
+      ->execute();
+    $this->assertResults(array('1', '2'));
+
+    // YES simple conditions, YES complex conditions, 'AND'.
+    $query = $this->factory->get('config_query_test', 'AND');
+    $and_condition_1 = $query->orConditionGroup()
+      ->condition('id', '2')
+      ->condition('label', $this->entities[0]->label);
+    $and_condition_2 = $query->orConditionGroup()
+      ->condition('id', 1)
+      ->condition('label', $this->entities[3]->label);
+    $this->queryResults = $query
+      ->condition('number', 31)
+      ->condition($and_condition_1)
+      ->condition($and_condition_2)
+      ->execute();
+    $this->assertResults(array('1'));
+
+    // YES simple conditions, YES complex conditions, 'OR'.
+    $query = $this->factory->get('config_query_test', 'OR');
+    $and_condition_1 = $query->orConditionGroup()
+      ->condition('id', '2')
+      ->condition('label', $this->entities[0]->label);
+    $and_condition_2 = $query->orConditionGroup()
+      ->condition('id', 1)
+      ->condition('label', $this->entities[3]->label);
+    $this->queryResults = $query
+      ->condition('number', 53)
+      ->condition($and_condition_1)
+      ->condition($and_condition_2)
+      ->execute();
+    $this->assertResults(array('1', '2', '4', '5'));
+  }
+
+  /**
+   * Test count query.
+   */
+  protected function testCount() {
+    // Test count on no conditions.
+    $count = $this->factory->get('config_query_test')
+      ->count()
+      ->execute();
+    $this->assertIdentical($count, count($this->entities));
+
+    // Test count on a complex query.
+    $query = $this->factory->get('config_query_test', 'OR');
+    $and_condition_1 = $query->andConditionGroup()
+      ->condition('id', 1)
+      ->condition('label', $this->entities[0]->label);
+    $and_condition_2 = $query->andConditionGroup()
+      ->condition('id', '2')
+      ->condition('label', $this->entities[1]->label);
+    $count = $query
+      ->condition($and_condition_1)
+      ->condition($and_condition_2)
+      ->count()
+      ->execute();
+    $this->assertIdentical($count, 2);
+  }
+
+  /**
+   * Tests sorting and range on config entity queries.
+   */
+  protected function testSortRange() {
+    // Sort by simple ascending/descending.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->sort('number', 'DESC')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('3', '5', '2', '1', '4'));
+
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->sort('number', 'ASC')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('4', '1', '2', '5', '3'));
+
+    // Apply some filters and sort.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '3', '>')
+      ->sort('number', 'DESC')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('5', '4'));
+
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('id', '3', '>')
+      ->sort('number', 'ASC')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('4', '5'));
+
+    // Apply a pager and sort.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->sort('number', 'DESC')
+      ->range('2', '2')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('2', '1'));
+
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->sort('number', 'ASC')
+      ->range('2', '2')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('2', '5'));
+
+    // Add a range to a query without a start parameter.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->range(0, '3')
+      ->sort('id', 'ASC')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('1', '2', '3'));
+
+    // Apply a pager with limit 4.
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->pager('4', 0)
+      ->sort('id', 'ASC')
+      ->execute();
+    $this->assertIdentical(array_values($this->queryResults), array('1', '2', '3', '4'));
+  }
+
+  /**
+   * Test wildcard matching.
+   */
+  function testWildcards() {
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('array.level1.*.level3', 1)
+      ->execute();
+    $this->assertResults(array('1', '3'));
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('*.level1.level2.level3', 2)
+      ->execute();
+    $this->assertResults(array('2', '4'));
+    $this->queryResults = $this->factory->get('config_query_test')
+      ->condition('array.level1.level2.*', 3)
+      ->execute();
+    $this->assertResults(array('5'));
+  }
+
+  /**
+   * Asserts the results as expected regardless of order.
+   *
+   * @param array $expected
+   *   Array of expected entity IDs.
+   */
+  function assertResults($expected) {
+    $this->assertIdentical(count($this->queryResults), count($expected));
+    foreach ($expected as $value) {
+      // This also tests whether $this->queryResults[$value] is even set at
+      // all.
+      $this->assertIdentical($this->queryResults[$value], $value);
+    }
+  }
+
+}
