Просмотр исходного кода

Reimplement from scratch client configuration.

This commit is a complete rewrite of the classes previously contained
in the Predis\Option namespace aimed at lowering the initialization
overhead while bringing in more consistency. The overall idea is still
the same with a mini DI container, Predis\Configuration\Options, which
carries options with values that can be initialized lazily.

The first difference with our previous implementation is that now even
user-defined options can be initialized lazily, everything needed is
an object responding to the __invoke() magic method such as a closure.
Other kind of callable arguments (strings, arrays) will be treated as
plain values. The only drawback is that we cannot pass any instance of
classes implementing __invoke() as an option value, but considered the
limited scope of our use case we can say it's more of an acceptable
compromise. Callbacks used for lazy initialization will receive two
arguments upon invokation:

  - The current instance of Predis\Configuration\Option ($options)
  - A string containing the name of the option ($option)

This is an example in actual code:

  $options = new Predis\Configuration\Options([
    'exceptions' => true,
    'profile' => '2.8',
    'distributor' => function () {
      return new Predis\Cluster\Distribution\KetamaPureRing();
    },
    'cluster' => function ($options) {
      $distr    = $options->distributor;
      $strategy = new Predis\Cluster\PredisClusterHashStrategy($distr);
      $cluster  = new Predis\Connection\PredisCluster();

      return $cluster;
    },
    'connections' => function ($options, $option) {
      $factory = $options->getDefault($option);
      $factory->define('tcp', 'Predis\Connection\PhpiredisConnection');

      return $factory;
    },
  ]);

As you can see there's very little difference compared to before in
the actual usage as most changes are under the hood. Some options such
as "exceptions" and "replication" can now correctly parse bool values
from strings (so the string "false" is not evaluated as boolean true).

While options were initially conceived to configure the client and its
behavior, the concept has matured and it's perfectly fine to consider
the use of Predis\Configuration\Options to propagate configurations to
inner parts of the library.
Daniele Alessandri 11 лет назад
Родитель
Сommit
b1ebc8df2f
38 измененных файлов с 1201 добавлено и 1649 удалено
  1. 9 0
      CHANGELOG.md
  2. 13 12
      lib/Predis/Client.php
  3. 2 2
      lib/Predis/ClientInterface.php
  4. 72 0
      lib/Predis/Configuration/ClusterOption.php
  5. 53 0
      lib/Predis/Configuration/ConnectionFactoryOption.php
  6. 8 6
      lib/Predis/Configuration/ExceptionsOption.php
  7. 37 0
      lib/Predis/Configuration/OptionInterface.php
  8. 117 0
      lib/Predis/Configuration/Options.php
  9. 54 0
      lib/Predis/Configuration/OptionsInterface.php
  10. 14 4
      lib/Predis/Configuration/PrefixOption.php
  11. 65 0
      lib/Predis/Configuration/ProfileOption.php
  12. 56 0
      lib/Predis/Configuration/ReplicationOption.php
  13. 0 48
      lib/Predis/Option/AbstractOption.php
  14. 0 95
      lib/Predis/Option/ClientCluster.php
  15. 0 73
      lib/Predis/Option/ClientConnectionFactory.php
  16. 0 125
      lib/Predis/Option/ClientOptions.php
  17. 0 21
      lib/Predis/Option/ClientOptionsInterface.php
  18. 0 61
      lib/Predis/Option/ClientProfile.php
  19. 0 78
      lib/Predis/Option/ClientReplication.php
  20. 0 89
      lib/Predis/Option/CustomOption.php
  21. 0 45
      lib/Predis/Option/OptionInterface.php
  22. 2 2
      tests/Predis/ClientTest.php
  23. 84 0
      tests/Predis/Configuration/ClusterOptionTest.php
  24. 88 0
      tests/Predis/Configuration/ConnectionFactoryOptionTest.php
  25. 67 0
      tests/Predis/Configuration/ExceptionsOptionTest.php
  26. 181 0
      tests/Predis/Configuration/OptionsTest.php
  27. 46 0
      tests/Predis/Configuration/PrefixOptionTest.php
  28. 165 0
      tests/Predis/Configuration/ProfileOptionTest.php
  29. 68 0
      tests/Predis/Configuration/ReplicationOptionTest.php
  30. 0 79
      tests/Predis/Option/AbstractOptionTest.php
  31. 0 127
      tests/Predis/Option/ClientClusterTest.php
  32. 0 138
      tests/Predis/Option/ClientConnectionFactoryTest.php
  33. 0 31
      tests/Predis/Option/ClientExceptionsTest.php
  34. 0 128
      tests/Predis/Option/ClientOptionsTest.php
  35. 0 59
      tests/Predis/Option/ClientPrefixTest.php
  36. 0 211
      tests/Predis/Option/ClientProfileTest.php
  37. 0 101
      tests/Predis/Option/ClientReplicationTest.php
  38. 0 114
      tests/Predis/Option/CustomOptionTest.php

+ 9 - 0
CHANGELOG.md

@@ -1,3 +1,12 @@
+v0.9.0 (201x-xx-xx)
+===============================================================================
+
+- The `Predis\Option` namespace is now known as `Predis\Configuration` and have
+  a fully-reworked `Options` class with the ability to lazily initialize values
+  using objects that responds to `__invoke()` (not all the kinds of callables)
+  even for custom options defined by the user.
+
+
 v0.8.5 (2013-xx-xx)
 ===============================================================================
 

+ 13 - 12
lib/Predis/Client.php

@@ -11,14 +11,15 @@
 
 namespace Predis;
 
+use InvalidArgumentException;
 use Predis\Command\CommandInterface;
 use Predis\Command\ScriptedCommand;
+use Predis\Configuration\Options;
+use Predis\Configuration\OptionsInterface;
 use Predis\Connection\AggregatedConnectionInterface;
 use Predis\Connection\ConnectionInterface;
 use Predis\Connection\ConnectionFactoryInterface;
 use Predis\Monitor\MonitorContext;
-use Predis\Option\ClientOptions;
-use Predis\Option\ClientOptionsInterface;
 use Predis\Pipeline\PipelineContext;
 use Predis\Profile\ServerProfile;
 use Predis\PubSub\PubSubContext;
@@ -45,34 +46,34 @@ class Client implements ClientInterface
      */
     public function __construct($parameters = null, $options = null)
     {
-        $this->options = $this->filterOptions($options);
+        $this->options = $this->createOptions($options);
         $this->profile = $this->options->profile;
         $this->connection = $this->initializeConnection($parameters);
     }
 
     /**
-     * Creates an instance of Predis\Option\ClientOptions from various types of
-     * arguments (string, array, Predis\Profile\ServerProfile) or returns the
-     * passed object if it is an instance of Predis\Option\ClientOptions.
+     * Creates a new instance of Predis\Configuration\Options from various
+     * types of arguments or returns the passed object if it is an instance
+     * of Predis\Configuration\OptionsInterface.
      *
      * @param mixed $options Client options.
-     * @return ClientOptions
+     * @return OptionsInterface
      */
-    protected function filterOptions($options)
+    protected function createOptions($options)
     {
         if (!isset($options)) {
-            return new ClientOptions();
+            return new Options();
         }
 
         if (is_array($options)) {
-            return new ClientOptions($options);
+            return new Options($options);
         }
 
-        if ($options instanceof ClientOptionsInterface) {
+        if ($options instanceof OptionsInterface) {
             return $options;
         }
 
-        throw new \InvalidArgumentException("Invalid type for client options");
+        throw new InvalidArgumentException("Invalid type for client options");
     }
 
     /**

+ 2 - 2
lib/Predis/ClientInterface.php

@@ -11,8 +11,8 @@
 
 namespace Predis;
 
+use Predis\Configuration\OptionsInterface;
 use Predis\Connection\ConnectionInterface;
-use Predis\Option\ClientOptionsInterface;
 use Predis\Profile\ServerProfileInterface;
 
 /**
@@ -34,7 +34,7 @@ interface ClientInterface extends BasicClientInterface
     /**
      * Returns the client options specified upon initialization.
      *
-     * @return ClientOptionsInterface
+     * @return OptionsInterface
      */
     public function getOptions();
 

+ 72 - 0
lib/Predis/Configuration/ClusterOption.php

@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use InvalidArgumentException;
+use Predis\Connection\ClusterConnectionInterface;
+use Predis\Connection\PredisCluster;
+use Predis\Connection\RedisCluster;
+
+/**
+ * Configures an aggregate connection used for clustering
+ * multiple Redis nodes using various implementations with
+ * different algorithms or strategies.
+ *
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class ClusterOption implements OptionInterface
+{
+    /**
+     * Creates a new cluster connection from on a known descriptive name.
+     *
+     * @param OptionsInterface $options Instance of the client options.
+     * @param string $id Descriptive identifier of the cluster type (`predis`, `redis-cluster`)
+     * @return ClusterConnectionInterface
+     */
+    protected function createByDescription(OptionsInterface $options, $id)
+    {
+        switch ($id) {
+            case 'predis':
+            case 'predis-cluster':
+                return new PredisCluster();
+
+            case 'redis':
+            case 'redis-cluster':
+                return new RedisCluster($options->connections);
+
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function filter(OptionsInterface $options, $value)
+    {
+        if (is_string($value)) {
+            $value = $this->createByDescription($options, $value);
+        }
+
+        if (!$value instanceof ClusterConnectionInterface) {
+            throw new InvalidArgumentException('Instance of Predis\Connection\ClusterConnectionInterface expected');
+        }
+
+        return $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDefault(OptionsInterface $options)
+    {
+        return new PredisCluster();
+    }
+}

+ 53 - 0
lib/Predis/Configuration/ConnectionFactoryOption.php

@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use InvalidArgumentException;
+use Predis\Connection\ConnectionFactory;
+use Predis\Connection\ConnectionFactoryInterface;
+
+/**
+ * Configures a connection factory used by the client to
+ * create new connection instances to single Redis nodes.
+ *
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class ConnectionFactoryOption implements OptionInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function filter(OptionsInterface $options, $value)
+    {
+        if ($value instanceof ConnectionFactoryInterface) {
+            return $value;
+        } else if (is_array($value)) {
+            $factory = $this->getDefault($options);
+
+            foreach ($value as $scheme => $initializer) {
+                $factory->define($scheme, $initializer);
+            }
+
+            return $factory;
+        } else {
+            throw new InvalidArgumentException('Invalid value for the connections option');
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDefault(OptionsInterface $options)
+    {
+        return new ConnectionFactory($options->profile);
+    }
+}

+ 8 - 6
lib/Predis/Option/ClientExceptions.php → lib/Predis/Configuration/ExceptionsOption.php

@@ -9,27 +9,29 @@
  * file that was distributed with this source code.
  */
 
-namespace Predis\Option;
+namespace Predis\Configuration;
 
 /**
- * Option class used to specify if the client should throw server exceptions.
+ * Configures whether consumers (such as the client) should
+ * throw exceptions on Redis errors (-ERR responses) or just
+ * return error objects.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-class ClientExceptions extends AbstractOption
+class ExceptionsOption implements OptionInterface
 {
     /**
      * {@inheritdoc}
      */
-    public function filter(ClientOptionsInterface $options, $value)
+    public function filter(OptionsInterface $options, $value)
     {
-        return (bool) $value;
+        return filter_var($value, FILTER_VALIDATE_BOOLEAN);
     }
 
     /**
      * {@inheritdoc}
      */
-    public function getDefault(ClientOptionsInterface $options)
+    public function getDefault(OptionsInterface $options)
     {
         return true;
     }

+ 37 - 0
lib/Predis/Configuration/OptionInterface.php

@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+/**
+ * Defines an handler used by Predis\Configuration\Options to
+ * filter, validate or get default values for a given option.
+ *
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+interface OptionInterface
+{
+    /**
+     * Filters and validates the passed value.
+     *
+     * @param mixed $value Input value.
+     * @return mixed
+     */
+    public function filter(OptionsInterface $options, $value);
+
+    /**
+     * Returns the default value for the option.
+     *
+     * @param mixed $value Input value.
+     * @return mixed
+     */
+    public function getDefault(OptionsInterface $options);
+}

+ 117 - 0
lib/Predis/Configuration/Options.php

@@ -0,0 +1,117 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+/**
+ * Manages Predis options with filtering, conversion and lazy
+ * initialization of values using a mini DI container approach.
+ *
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class Options implements OptionsInterface
+{
+    protected $input;
+    protected $options;
+    protected $handlers;
+
+    /**
+     * @param array $options Array of options with their values
+     */
+    public function __construct(array $options = array())
+    {
+        $this->input = $options;
+        $this->options = array();
+        $this->handlers = $this->getHandlers();
+    }
+
+    /**
+     * Ensures that the default options are initialized.
+     *
+     * @return array
+     */
+    protected function getHandlers()
+    {
+        return array(
+            'cluster'     => 'Predis\Configuration\ClusterOption',
+            'connections' => 'Predis\Configuration\ConnectionFactoryOption',
+            'exceptions'  => 'Predis\Configuration\ExceptionsOption',
+            'prefix'      => 'Predis\Configuration\PrefixOption',
+            'profile'     => 'Predis\Configuration\ProfileOption',
+            'replication' => 'Predis\Configuration\ReplicationOption',
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDefault($option)
+    {
+        if (isset($this->handlers[$option])) {
+            $handler = $this->handlers[$option];
+            $handler = new $handler();
+            return $handler->getDefault($this);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function defined($option)
+    {
+        return (
+            array_key_exists($option, $this->options) ||
+            array_key_exists($option, $this->input)
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __isset($option)
+    {
+        return (
+            array_key_exists($option, $this->options) ||
+            array_key_exists($option, $this->input)
+        ) && $this->__get($option) !== null;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __get($option)
+    {
+        if (isset($this->options[$option]) || array_key_exists($option, $this->options)) {
+            return $this->options[$option];
+        }
+
+        if (isset($this->input[$option]) || array_key_exists($option, $this->input)) {
+            $value = $this->input[$option];
+            unset($this->input[$option]);
+
+            if (method_exists($value, '__invoke')) {
+                $value = $value($this, $option);
+            }
+
+            if (isset($this->handlers[$option])) {
+                $handler = $this->handlers[$option];
+                $handler = new $handler();
+                $value = $handler->filter($this, $value);
+            }
+
+            return $this->options[$option] = $value;
+        }
+
+        if (isset($this->handlers[$option])) {
+            return $this->options[$option] = $this->getDefault($option);
+        }
+    }
+}

+ 54 - 0
lib/Predis/Configuration/OptionsInterface.php

@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+/**
+ * Defines an options container class.
+ *
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+interface OptionsInterface
+{
+    /**
+     * Returns the default value for the specified option.
+     *
+     * @param string $option Name of the option.
+     * @return mixed
+     */
+    public function getDefault($option);
+
+    /**
+     * Checks if the specified option has been passed by
+     * the user at construction time.
+     *
+     * @param string $option Name of the option.
+     * @return bool
+     */
+    public function defined($option);
+
+    /**
+     * Checks if the specified option has been set and
+     * does not evaluate to NULL.
+     *
+     * @param string $option Name of the option.
+     * @return bool
+     */
+    public function __isset($option);
+
+    /**
+     * Returns the value of the specified option.
+     *
+     * @param string $option Name of the option.
+     * @return mixed
+     */
+    public function __get($option);
+}

+ 14 - 4
lib/Predis/Option/ClientPrefix.php → lib/Predis/Configuration/PrefixOption.php

@@ -9,22 +9,32 @@
  * file that was distributed with this source code.
  */
 
-namespace Predis\Option;
+namespace Predis\Configuration;
 
 use Predis\Command\Processor\KeyPrefixProcessor;
 
 /**
- * Option class that handles the prefixing of keys in commands.
+ * Configures a command processor that apply the specified
+ * prefix string to a series of Redis commands considered
+ * prefixable.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-class ClientPrefix extends AbstractOption
+class PrefixOption implements OptionInterface
 {
     /**
      * {@inheritdoc}
      */
-    public function filter(ClientOptionsInterface $options, $value)
+    public function filter(OptionsInterface $options, $value)
     {
         return new KeyPrefixProcessor($value);
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDefault(OptionsInterface $options)
+    {
+        // NOOP
+    }
 }

+ 65 - 0
lib/Predis/Configuration/ProfileOption.php

@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use InvalidArgumentException;
+use Predis\Profile\ServerProfile;
+use Predis\Profile\ServerProfileInterface;
+
+/**
+ * Configures the server profile to be used by the client
+ * to create command instances depending on the specified
+ * version of the Redis server.
+ *
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class ProfileOption implements OptionInterface
+{
+    /**
+     * Sets the needed commands processors that should be applied to the profile.
+     *
+     * @param OptionsInterface $options Client options.
+     * @param ServerProfileInterface $profile Server profile.
+     */
+    protected function setProcessors(OptionsInterface $options, ServerProfileInterface $profile)
+    {
+        if (isset($options->prefix)) {
+            $profile->setProcessor($options->prefix);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function filter(OptionsInterface $options, $value)
+    {
+        if (is_string($value)) {
+            $value = ServerProfile::get($value);
+            $this->setProcessors($options, $value);
+        } else if (!$value instanceof ServerProfileInterface) {
+            throw new InvalidArgumentException('Invalid value for the profile option');
+        }
+
+        return $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDefault(OptionsInterface $options)
+    {
+        $profile = ServerProfile::getDefault();
+        $this->setProcessors($options, $profile);
+
+        return $profile;
+    }
+}

+ 56 - 0
lib/Predis/Configuration/ReplicationOption.php

@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use InvalidArgumentException;
+use Predis\Connection\MasterSlaveReplication;
+use Predis\Connection\ReplicationConnectionInterface;
+
+/**
+ * Configures an aggregate connection used for master/slave
+ * replication between multiple nodes.
+ *
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class ReplicationOption implements OptionInterface
+{
+    /**
+     * {@inheritdoc}
+     *
+     * @todo There's more code than needed due to a bug in filter_var()
+     *       as discussed here https://bugs.php.net/bug.php?id=49510.
+     */
+    public function filter(OptionsInterface $options, $value)
+    {
+        if ($value instanceof ReplicationConnectionInterface) {
+            return $value;
+        }
+
+        if (is_bool($value)) {
+            return $value ? $this->getDefault($options) : null;
+        }
+
+        if (!is_object($value) && null !== $asbool = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)) {
+            return $asbool ? $this->getDefault($options) : null;
+        }
+
+        throw new InvalidArgumentException('Instance of Predis\Connection\ReplicationConnectionInterface expected');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDefault(OptionsInterface $options)
+    {
+        return new MasterSlaveReplication();
+    }
+}

+ 0 - 48
lib/Predis/Option/AbstractOption.php

@@ -1,48 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-/**
- * Implements a client option.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-abstract class AbstractOption implements OptionInterface
-{
-    /**
-     * {@inheritdoc}
-     */
-    public function filter(ClientOptionsInterface $options, $value)
-    {
-        return $value;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getDefault(ClientOptionsInterface $options)
-    {
-        return null;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function __invoke(ClientOptionsInterface $options, $value)
-    {
-        if (isset($value)) {
-            return $this->filter($options, $value);
-        }
-
-        return $this->getDefault($options);
-    }
-}

+ 0 - 95
lib/Predis/Option/ClientCluster.php

@@ -1,95 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use Predis\Connection\ClusterConnectionInterface;
-use Predis\Connection\PredisCluster;
-use Predis\Connection\RedisCluster;
-
-/**
- * Option class that returns a connection cluster to be used by a client.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-class ClientCluster extends AbstractOption
-{
-    /**
-     * Checks if the specified value is a valid instance of ClusterConnectionInterface.
-     *
-     * @param ClusterConnectionInterface $cluster Instance of a connection cluster.
-     * @return ClusterConnectionInterface
-     */
-    protected function checkInstance($cluster)
-    {
-        if (!$cluster instanceof ClusterConnectionInterface) {
-            throw new \InvalidArgumentException('Instance of Predis\Connection\ClusterConnectionInterface expected');
-        }
-
-        return $cluster;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function filter(ClientOptionsInterface $options, $value)
-    {
-        if (is_callable($value)) {
-            return $this->checkInstance(call_user_func($value, $options, $this));
-        }
-
-        $initializer = $this->getInitializer($options, $value);
-
-        return $this->checkInstance($initializer());
-    }
-
-    /**
-     * Returns an initializer for the specified FQN or type.
-     *
-     * @param string $fqnOrType Type of cluster or FQN of a class implementing ClusterConnectionInterface.
-     * @param ClientOptionsInterface $options Instance of the client options.
-     * @return \Closure
-     */
-    protected function getInitializer(ClientOptionsInterface $options, $fqnOrType)
-    {
-        switch ($fqnOrType) {
-            case 'predis':
-                return function () {
-                    return new PredisCluster();
-                };
-
-            case 'redis':
-                return function () use ($options) {
-                    $connectionFactory = $options->connections;
-                    $cluster = new RedisCluster($connectionFactory);
-
-                    return $cluster;
-                };
-
-            default:
-                // TODO: we should not even allow non-string values here.
-                if (is_string($fqnOrType) && !class_exists($fqnOrType)) {
-                    throw new \InvalidArgumentException("Class $fqnOrType does not exist");
-                }
-                return function () use ($fqnOrType) {
-                    return new $fqnOrType();
-                };
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getDefault(ClientOptionsInterface $options)
-    {
-        return new PredisCluster();
-    }
-}

+ 0 - 73
lib/Predis/Option/ClientConnectionFactory.php

@@ -1,73 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use Predis\Connection\ConnectionFactory;
-use Predis\Connection\ConnectionFactoryInterface;
-
-/**
- * Option class that returns a connection factory to be used by a client.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-class ClientConnectionFactory extends AbstractOption
-{
-    /**
-     * {@inheritdoc}
-     */
-    public function filter(ClientOptionsInterface $options, $value)
-    {
-        if ($value instanceof ConnectionFactoryInterface) {
-            return $value;
-        }
-
-        if (is_array($value)) {
-            $factory = $this->getDefault($options);
-
-            foreach ($value as $scheme => $initializer) {
-                $factory->define($scheme, $initializer);
-            }
-
-            return $factory;
-        }
-
-        if (is_callable($value)) {
-            $factory = call_user_func($value, $options, $this);
-
-            if (!$factory instanceof ConnectionFactoryInterface) {
-                throw new \InvalidArgumentException('Instance of Predis\Connection\ConnectionFactoryInterface expected');
-            }
-
-            return $factory;
-        }
-
-        if (@class_exists($value)) {
-            $factory = new $value();
-
-            if (!$factory instanceof ConnectionFactoryInterface) {
-                throw new \InvalidArgumentException("Class $value must be an instance of Predis\Connection\ConnectionFactoryInterface");
-            }
-
-            return $factory;
-        }
-
-        throw new \InvalidArgumentException('Invalid value for the connections option');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getDefault(ClientOptionsInterface $options)
-    {
-        return new ConnectionFactory($options->profile);
-    }
-}

+ 0 - 125
lib/Predis/Option/ClientOptions.php

@@ -1,125 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-/**
- * Class that manages client options with filtering and conversion.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-class ClientOptions implements ClientOptionsInterface
-{
-    private $handlers;
-    private $defined;
-    private $options = array();
-
-    /**
-     * @param array $options Array of client options.
-     */
-    public function __construct(Array $options = array())
-    {
-        $this->handlers = $this->initialize($options);
-        $this->defined = array_fill_keys(array_keys($options), true);
-    }
-
-    /**
-     * Ensures that the default options are initialized.
-     *
-     * @return array
-     */
-    protected function getDefaultOptions()
-    {
-        return array(
-            'profile' => new ClientProfile(),
-            'connections' => new ClientConnectionFactory(),
-            'cluster' => new ClientCluster(),
-            'replication' => new ClientReplication(),
-            'prefix' => new ClientPrefix(),
-            'exceptions' => new ClientExceptions(),
-        );
-    }
-
-    /**
-     * Initializes client options handlers.
-     *
-     * @param array $options List of client options values.
-     * @return array
-     */
-    protected function initialize(Array $options)
-    {
-        $handlers = $this->getDefaultOptions();
-
-        foreach ($options as $option => $value) {
-            if (isset($handlers[$option])) {
-                $handler = $handlers[$option];
-                $handlers[$option] = function ($options) use ($handler, $value) {
-                    return $handler->filter($options, $value);
-                };
-            } else {
-                $this->options[$option] = $value;
-            }
-        }
-
-        return $handlers;
-    }
-
-    /**
-     * Checks if the specified option is set.
-     *
-     * @param string $option Name of the option.
-     * @return Boolean
-     */
-    public function __isset($option)
-    {
-        return isset($this->defined[$option]);
-    }
-
-    /**
-     * Returns the value of the specified option.
-     *
-     * @param string $option Name of the option.
-     * @return mixed
-     */
-    public function __get($option)
-    {
-        if (isset($this->options[$option])) {
-            return $this->options[$option];
-        }
-
-        if (isset($this->handlers[$option])) {
-            $handler = $this->handlers[$option];
-            $value = $handler instanceof OptionInterface ? $handler->getDefault($this) : $handler($this);
-            $this->options[$option] = $value;
-
-            return $value;
-        }
-    }
-
-    /**
-     * Returns the default value for the specified option.
-     *
-     * @param string|OptionInterface $option Name or instance of the option.
-     * @return mixed
-     */
-    public function getDefault($option)
-    {
-        if ($option instanceof OptionInterface) {
-            return $option->getDefault($this);
-        }
-
-        $options = $this->getDefaultOptions();
-
-        if (isset($options[$option])) {
-            return $options[$option]->getDefault($this);
-        }
-    }
-}

+ 0 - 21
lib/Predis/Option/ClientOptionsInterface.php

@@ -1,21 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-/**
- * Marker interface defining a client options bag.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-interface ClientOptionsInterface
-{
-}

+ 0 - 61
lib/Predis/Option/ClientProfile.php

@@ -1,61 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use Predis\Profile\ServerProfile;
-use Predis\Profile\ServerProfileInterface;
-
-/**
- * Option class that handles server profiles to be used by a client.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-class ClientProfile extends AbstractOption
-{
-    /**
-     * {@inheritdoc}
-     */
-    public function filter(ClientOptionsInterface $options, $value)
-    {
-        if (is_string($value)) {
-            $value = ServerProfile::get($value);
-
-            if (isset($options->prefix)) {
-                $value->setProcessor($options->prefix);
-            }
-        }
-
-        if (is_callable($value)) {
-            $value = call_user_func($value, $options, $this);
-        }
-
-        if (!$value instanceof ServerProfileInterface) {
-            throw new \InvalidArgumentException('Invalid value for the profile option');
-        }
-
-        return $value;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getDefault(ClientOptionsInterface $options)
-    {
-        $profile = ServerProfile::getDefault();
-
-        if (isset($options->prefix)) {
-            $profile->setProcessor($options->prefix);
-        }
-
-        return $profile;
-    }
-}

+ 0 - 78
lib/Predis/Option/ClientReplication.php

@@ -1,78 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use Predis\Connection\MasterSlaveReplication;
-use Predis\Connection\ReplicationConnectionInterface;
-
-/**
- * Option class that returns a replication connection be used by a client.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-class ClientReplication extends AbstractOption
-{
-    /**
-     * Checks if the specified value is a valid instance of ReplicationConnectionInterface.
-     *
-     * @param ReplicationConnectionInterface $connection Instance of a replication connection.
-     * @return ReplicationConnectionInterface
-     */
-    protected function checkInstance($connection)
-    {
-        if (!$connection instanceof ReplicationConnectionInterface) {
-            throw new \InvalidArgumentException('Instance of Predis\Connection\ReplicationConnectionInterface expected');
-        }
-
-        return $connection;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function filter(ClientOptionsInterface $options, $value)
-    {
-        if (is_callable($value)) {
-            $connection = call_user_func($value, $options, $this);
-
-            if (!$connection instanceof ReplicationConnectionInterface) {
-                throw new \InvalidArgumentException('Instance of Predis\Connection\ReplicationConnectionInterface expected');
-            }
-
-            return $connection;
-        }
-
-        if (is_string($value)) {
-            if (!class_exists($value)) {
-                throw new \InvalidArgumentException("Class $value does not exist");
-            }
-
-            if (!($connection = new $value()) instanceof ReplicationConnectionInterface) {
-                throw new \InvalidArgumentException('Instance of Predis\Connection\ReplicationConnectionInterface expected');
-            }
-
-            return $connection;
-        }
-
-        if ($value == true) {
-            return $this->getDefault($options);
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getDefault(ClientOptionsInterface $options)
-    {
-        return new MasterSlaveReplication();
-    }
-}

+ 0 - 89
lib/Predis/Option/CustomOption.php

@@ -1,89 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-/**
- * Implements a generic class used to dynamically define a client option.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-class CustomOption implements OptionInterface
-{
-    private $filter;
-    private $default;
-
-    /**
-     * @param array $options List of options
-     */
-    public function __construct(Array $options = array())
-    {
-        $this->filter = $this->ensureCallable($options, 'filter');
-        $this->default = $this->ensureCallable($options, 'default');
-    }
-
-    /**
-     * Checks if the specified value in the options array is a callable object.
-     *
-     * @param array $options Array of options
-     * @param string $key Target option.
-     */
-    private function ensureCallable($options, $key)
-    {
-        if (!isset($options[$key])) {
-            return;
-        }
-
-        if (is_callable($callable = $options[$key])) {
-            return $callable;
-        }
-
-        throw new \InvalidArgumentException("The parameter $key must be callable");
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function filter(ClientOptionsInterface $options, $value)
-    {
-        if (isset($value)) {
-            if ($this->filter === null) {
-                return $value;
-            }
-
-            return call_user_func($this->filter, $options, $value);
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getDefault(ClientOptionsInterface $options)
-    {
-        if (!isset($this->default)) {
-            return;
-        }
-
-        return call_user_func($this->default, $options);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function __invoke(ClientOptionsInterface $options, $value)
-    {
-        if (isset($value)) {
-            return $this->filter($options, $value);
-        }
-
-        return $this->getDefault($options);
-    }
-}

+ 0 - 45
lib/Predis/Option/OptionInterface.php

@@ -1,45 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-/**
- * Interface that defines a client option.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-interface OptionInterface
-{
-    /**
-     * Filters (and optionally converts) the passed value.
-     *
-     * @param mixed $value Input value.
-     * @return mixed
-     */
-    public function filter(ClientOptionsInterface $options, $value);
-
-    /**
-     * Returns a default value for the option.
-     *
-     * @param mixed $value Input value.
-     * @return mixed
-     */
-    public function getDefault(ClientOptionsInterface $options);
-
-    /**
-     * Filters a value and, if no value is specified, returns
-     * the default one defined by the option.
-     *
-     * @param mixed $value Input value.
-     * @return mixed
-     */
-    public function __invoke(ClientOptionsInterface $options, $value);
-}

+ 2 - 2
tests/Predis/ClientTest.php

@@ -207,7 +207,7 @@ class ClientTest extends StandardTestCase
         $callable = $this->getMock('stdClass', array('__invoke'));
         $callable->expects($this->once())
                  ->method('__invoke')
-                 ->with($this->isInstanceOf('Predis\Option\ClientOptions'))
+                 ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
                  ->will($this->returnValue($connection));
 
         $client = new Client($callable);
@@ -227,7 +227,7 @@ class ClientTest extends StandardTestCase
         $callable = $this->getMock('stdClass', array('__invoke'));
         $callable->expects($this->once())
                  ->method('__invoke')
-                 ->with($this->isInstanceOf('Predis\Option\ClientOptions'))
+                 ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
                  ->will($this->returnValue($wrongType));
 
         $client = new Client($callable);

+ 84 - 0
tests/Predis/Configuration/ClusterOptionTest.php

@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use PHPUnit_Framework_TestCase as StandardTestCase;
+use stdClass;
+
+/**
+ *
+ */
+class ClusterOptionTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testDefaultOptionValue()
+    {
+        $option = new ClusterOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertInstanceOf('Predis\Connection\PredisCluster', $option->getDefault($options));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsInstanceOfClusterConnectionInterface()
+    {
+        $option = new ClusterOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+        $cluster = $this->getMock('Predis\Connection\ClusterConnectionInterface');
+
+        $this->assertSame($cluster, $option->filter($options, $cluster));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsPredefinedShortNameString()
+    {
+        $option = new ClusterOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertInstanceOf('Predis\Connection\PredisCluster', $option->filter($options, 'predis'));
+        $this->assertInstanceOf('Predis\Connection\PredisCluster', $option->filter($options, 'predis-cluster'));
+
+        $this->assertInstanceOf('Predis\Connection\RedisCluster', $option->filter($options, 'redis'));
+        $this->assertInstanceOf('Predis\Connection\RedisCluster', $option->filter($options, 'redis-cluster'));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException InvalidArgumentException
+     */
+    public function testThrowsExceptionOnInvalidInstanceType()
+    {
+        $option = new ClusterOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+        $class = $this->getMock('Predis\Connection\SingleConnectionInterface');
+
+        $option->filter($options, $class);
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException InvalidArgumentException
+     */
+    public function testThrowsExceptionOnInvalidShortNameString()
+    {
+        $option = new ClusterOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $option->filter($options, 'unknown');
+    }
+}

+ 88 - 0
tests/Predis/Configuration/ConnectionFactoryOptionTest.php

@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use InvalidArgumentException;
+use PHPUnit_Framework_TestCase as StandardTestCase;
+use stdClass;
+
+use Predis\Connection\ConnectionFactory;
+
+/**
+ *
+ */
+class ConnectionFactoryOptionTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testDefaultOptionValue()
+    {
+        $option = new ConnectionFactoryOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertInstanceOf('Predis\Connection\ConnectionFactory', $option->getDefault($options));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsNamedArrayWithSchemeToConnectionClassMappings()
+    {
+        $option = new ConnectionFactoryOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $class = get_class($this->getMock('Predis\Connection\SingleConnectionInterface'));
+        $value = array('tcp' => $class, 'redis' => $class);
+
+        $default = $this->getMock('Predis\Connection\ConnectionFactoryInterface');
+        $default->expects($this->exactly(2))
+                ->method('define')
+                ->with($this->matchesRegularExpression('/^tcp|redis$/'), $class);
+
+        $option = $this->getMock('Predis\Configuration\ConnectionFactoryOption', array('getDefault'));
+        $option->expects($this->once())
+               ->method('getDefault')
+               ->with($options)
+               ->will($this->returnValue($default));
+
+        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $factory = $option->filter($options, $value));
+        $this->assertSame($default, $factory);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsConnectionFactoryInstance()
+    {
+        $option = new ConnectionFactoryOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+        $value = $this->getMock('Predis\Connection\ConnectionFactoryInterface');
+
+        $option = $this->getMock('Predis\Configuration\ConnectionFactoryOption', array('getDefault'));
+        $option->expects($this->never())->method('getDefault');
+
+        $this->assertSame($value, $option->filter($options, $value));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException InvalidArgumentException
+     */
+    public function testThrowsExceptionOnInvalidArguments()
+    {
+        $option = new ConnectionFactoryOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $option->filter($options, new stdClass);
+    }
+}

+ 67 - 0
tests/Predis/Configuration/ExceptionsOptionTest.php

@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use PHPUnit_Framework_TestCase as StandardTestCase;
+use stdClass;
+
+/**
+ *
+ */
+class ExceptionsOptionTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testDefaultOptionValue()
+    {
+        $option = new ExceptionsOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertTrue($option->getDefault($options));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsDifferentValuesAndFiltersThemAsBooleans()
+    {
+        $option = new ExceptionsOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertFalse($option->filter($options, null));
+
+        $this->assertTrue($option->filter($options, true));
+        $this->assertFalse($option->filter($options, false));
+
+        $this->assertTrue($option->filter($options, 1));
+        $this->assertFalse($option->filter($options, 0));
+
+        $this->assertTrue($option->filter($options, 'true'));
+        $this->assertFalse($option->filter($options, 'false'));
+
+        $this->assertTrue($option->filter($options, 'on'));
+        $this->assertFalse($option->filter($options, 'off'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testReturnsFalesOnValuesNotParsableAsBooleans()
+    {
+        $option = new ExceptionsOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertFalse($option->filter($options, new stdClass));
+        $this->assertFalse($option->filter($options, 'invalid'));
+    }
+}

+ 181 - 0
tests/Predis/Configuration/OptionsTest.php

@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use PHPUnit_Framework_TestCase as StandardTestCase;
+use stdClass;
+
+/**
+ * @todo We should test the inner work performed by this class
+ *       using mock objects, but it is quite hard to to that.
+ */
+class OptionsTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testConstructorWithoutArguments()
+    {
+        $options = new Options();
+
+        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $options->connections);
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $options->profile);
+        $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $options->cluster);
+        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $options->replication);
+        $this->assertTrue($options->exceptions);
+        $this->assertNull($options->prefix);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testConstructorWithArrayArgument()
+    {
+        $options = new Options(array(
+            'exceptions'  => false,
+            'profile'     => '2.0',
+            'prefix'      => 'prefix:',
+            'connections' => $this->getMock('Predis\Connection\ConnectionFactoryInterface'),
+            'cluster'     => $this->getMock('Predis\Connection\ClusterConnectionInterface'),
+            'replication' => $this->getMock('Predis\Connection\ReplicationConnectionInterface'),
+        ));
+
+        $this->assertInternalType('bool', $options->exceptions);
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $options->profile);
+        $this->assertInstanceOf('Predis\Command\Processor\CommandProcessorInterface', $options->prefix);
+        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $options->connections);
+        $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $options->cluster);
+        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $options->replication);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testSupportsCustomOptions()
+    {
+        $options = new Options(array(
+            'custom' => 'foobar',
+        ));
+
+        $this->assertSame('foobar', $options->custom);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testUndefinedOptionsReturnNull()
+    {
+        $options = new Options();
+
+        $this->assertFalse($options->defined('unknown'));
+        $this->assertFalse(isset($options->unknown));
+        $this->assertNull($options->unknown);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testCanCheckOptionsIfDefinedByUser()
+    {
+        $options = new Options(array(
+            'prefix' => 'prefix:',
+            'custom' => 'foobar',
+            'void'   => null,
+        ));
+
+        $this->assertTrue($options->defined('prefix'));
+        $this->assertTrue($options->defined('custom'));
+        $this->assertTrue($options->defined('void'));
+        $this->assertFalse($options->defined('profile'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testIsSetReplicatesPHPBehavior()
+    {
+        $options = new Options(array(
+            'prefix' => 'prefix:',
+            'custom' => 'foobar',
+            'void'   => null,
+        ));
+
+        $this->assertTrue(isset($options->prefix));
+        $this->assertTrue(isset($options->custom));
+        $this->assertFalse(isset($options->void));
+        $this->assertFalse(isset($options->profile));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testReturnsDefaultValueOfSpecifiedOption()
+    {
+        $options = new Options();
+
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $options->getDefault('profile'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testReturnsNullAsDefaultValueForUndefinedOption()
+    {
+        $options = new Options();
+
+        $this->assertNull($options->getDefault('unknown'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testLazilyInitializesOptionValueUsingObjectWithInvokeMagicMethod()
+    {
+        $profile = $this->getMock('Predis\Profile\ServerProfileInterface');
+
+        // NOTE: closure values are covered by this test since they define __invoke().
+        $callable = $this->getMock('stdClass', array('__invoke'));
+        $callable->expects($this->once())
+                 ->method('__invoke')
+                 ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'), 'profile')
+                 ->will($this->returnValue($profile));
+
+        $options = new Options(array(
+            'profile' => $callable,
+        ));
+
+        $this->assertSame($profile, $options->profile);
+        $this->assertSame($profile, $options->profile);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testLazilyInitializesCustomOptionValueUsingObjectWithInvokeMagicMethod()
+    {
+        $custom = new stdClass;
+
+        // NOTE: closure values are covered by this test since they define __invoke().
+        $callable = $this->getMock('stdClass', array('__invoke'));
+        $callable->expects($this->once())
+                 ->method('__invoke')
+                 ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'), 'custom')
+                 ->will($this->returnValue($custom));
+
+        $options = new Options(array(
+            'custom' => $callable,
+        ));
+
+        $this->assertSame($custom, $options->custom);
+        $this->assertSame($custom, $options->custom);
+    }
+}

+ 46 - 0
tests/Predis/Configuration/PrefixOptionTest.php

@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class PrefixOptionTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testDefaultOptionValue()
+    {
+        $option = new PrefixOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertNull($option->getDefault($options));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsStringAndReturnsCommandProcessor()
+    {
+        $option = new PrefixOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $return = $option->filter($options, $value = 'prefix:');
+
+        $this->assertInstanceOf('Predis\Command\Processor\CommandProcessorInterface', $return);
+        $this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $return);
+        $this->assertSame($value, $return->getPrefix());
+    }
+}

+ 165 - 0
tests/Predis/Configuration/ProfileOptionTest.php

@@ -0,0 +1,165 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use InvalidArgumentException;
+use PHPUnit_Framework_TestCase as StandardTestCase;
+use stdClass;
+
+use Predis\Command\Processor\KeyPrefixProcessor;
+use Predis\Profile\ServerProfile;
+
+/**
+ *
+ */
+class ProfileOptionTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testDefaultOptionValue()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $profile = $option->getDefault($options);
+
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
+        $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile);
+        $this->assertNull($profile->getProcessor());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsServerProfileInstanceAsValue()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+        $value = ServerProfile::get('2.0');
+
+        $profile = $option->filter($options, $value);
+
+        $this->assertSame($profile, $value);
+        $this->assertNull($profile->getProcessor());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsStringInterpretedAsServerProfileVersion()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $profile = $option->filter($options, '2.0');
+
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
+        $this->assertEquals('2.0', $profile->getVersion());
+        $this->assertNull($profile->getProcessor());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAppliesPrefixOnDefaultOptionValue()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $options->expects($this->once())
+                ->method('__isset')
+                ->with('prefix')
+                ->will($this->returnValue(true));
+        $options->expects($this->once())
+                ->method('__get')
+                ->with('prefix')
+                ->will($this->returnValue(new KeyPrefixProcessor('prefix:')));
+
+        $profile = $option->getDefault($options);
+
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
+        $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile);
+
+        $this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $profile->getProcessor());
+        $this->assertSame('prefix:', $profile->getProcessor()->getPrefix());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAppliesPrefixOnProfileCreatedFromStringValue()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $options->expects($this->once())
+                ->method('__isset')
+                ->with('prefix')
+                ->will($this->returnValue(true));
+        $options->expects($this->once())
+                ->method('__get')
+                ->with('prefix')
+                ->will($this->returnValue(new KeyPrefixProcessor('prefix:')));
+
+        $profile = $option->filter($options, '2.0');
+
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
+        $this->assertInstanceOf(get_class(ServerProfile::get('2.0')), $profile);
+
+        $this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $profile->getProcessor());
+        $this->assertSame('prefix:', $profile->getProcessor()->getPrefix());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testDoesNotApplyPrefixOnServerProfileValue()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+        $value = ServerProfile::getDefault();
+
+        $options->expects($this->never())->method('__isset');
+        $options->expects($this->never())->method('__get');
+
+        $profile = $option->filter($options, $value);
+
+        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
+        $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile);
+        $this->assertNull($profile->getProcessor());
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException InvalidArgumentException
+     */
+    public function testThrowsExceptionOnInvalidValue()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $option->filter($options, new stdClass);
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\ClientException
+     */
+    public function testThrowsExceptionOnUnrecognizedVersionString()
+    {
+        $option = new ProfileOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $option->filter($options, '0.0');
+    }
+}

+ 68 - 0
tests/Predis/Configuration/ReplicationOptionTest.php

@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Configuration;
+
+use PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class ReplicationOptionTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testDefaultOptionValue()
+    {
+        $option = new ReplicationOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $option->getDefault($options));
+        $this->assertInstanceOf('Predis\Connection\MasterSlaveReplication', $option->getDefault($options));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testAcceptsValuesThatCanBeInterpretedAsBooleans()
+    {
+        $option = new ReplicationOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+
+        $this->assertNull($option->filter($options, null));
+
+        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $option->filter($options, true));
+        $this->assertNull($option->filter($options, false));
+
+        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $option->filter($options, 1));
+        $this->assertNull($option->filter($options, 0));
+
+        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $option->filter($options, 'true'));
+        $this->assertNull($option->filter($options, 'false'));
+
+        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $option->filter($options, 'on'));
+        $this->assertNull($option->filter($options, 'off'));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException InvalidArgumentException
+     */
+    public function testThrowsExceptionOnInvalidInstanceType()
+    {
+        $option = new ReplicationOption();
+        $options = $this->getMock('Predis\Configuration\OptionsInterface');
+        $value = $this->getMock('Predis\Connection\SingleConnectionInterface');
+
+        $option->filter($options, $value);
+    }
+}

+ 0 - 79
tests/Predis/Option/AbstractOptionTest.php

@@ -1,79 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-/**
- *
- */
-class AbstractOptionTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testValidationReturnsTheSameObject()
-    {
-        $value = new \stdClass();
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = $this->getMockForAbstractClass('Predis\Option\AbstractOption');
-
-        $this->assertSame($value, $option->filter($options, $value));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testDefaultReturnsNull()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = $this->getMockForAbstractClass('Predis\Option\AbstractOption');
-
-        $this->assertNull($option->getDefault($options));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testInvokePerformsValidationWhenValueIsSet()
-    {
-        $value = new \stdClass();
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $option = $this->getMock('Predis\Option\AbstractOption', array('filter', 'getDefault'));
-        $option->expects($this->once())
-               ->method('filter')
-               ->with($options, $value)
-               ->will($this->returnValue($value));
-        $option->expects($this->never())->method('getDefault');
-
-        $this->assertSame($value, $option($options, $value));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testInvokeReturnsDefaultWhenValueIsNotSet()
-    {
-        $expected = new \stdClass();
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $option = $this->getMock('Predis\Option\AbstractOption', array('filter', 'getDefault'));
-        $option->expects($this->never())->method('filter');
-        $option->expects($this->once())
-               ->method('getDefault')
-               ->with($options)
-               ->will($this->returnValue($expected));
-
-        $this->assertSame($expected, $option($options, null));
-    }
-}

+ 0 - 127
tests/Predis/Option/ClientClusterTest.php

@@ -1,127 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-/**
- *
- */
-class ClientClusterTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsFQNStringAsInitializer()
-    {
-        $clusterClass = get_class($this->getMock('Predis\Connection\ClusterConnectionInterface'));
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientCluster();
-
-        $cluster = $option->filter($options, $clusterClass);
-
-        $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $cluster);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationRecognizesCertainPredefinedShortNames()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientCluster();
-
-        $cluster = $option->filter($options, 'predis');
-
-        $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $cluster);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsCallableObjectAsInitializers()
-    {
-        $value = $this->getMock('Predis\Connection\ClusterConnectionInterface');
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientCluster();
-
-        $initializer = $this->getMock('stdClass', array('__invoke'));
-        $initializer->expects($this->once())
-                    ->method('__invoke')
-                    ->with($this->isInstanceOf('Predis\Option\ClientOptionsInterface'), $option)
-                    ->will($this->returnValue($value));
-
-        $cluster = $option->filter($options, $initializer, $option);
-
-        $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $cluster);
-        $this->assertSame($value, $cluster);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationThrowsExceptionOnInvalidClassTypes()
-    {
-        $this->setExpectedException('InvalidArgumentException');
-
-        $connectionClass = get_class($this->getMock('Predis\Connection\SingleConnectionInterface'));
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientCluster();
-
-        $option->filter($options, $connectionClass);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationThrowsExceptionOnInvalidShortName()
-    {
-        $this->setExpectedException('InvalidArgumentException');
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientCluster();
-
-        $option->filter($options, 'unknown');
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationThrowsExceptionOnInvalidObjectReturnedByCallback()
-    {
-        $this->setExpectedException('InvalidArgumentException');
-
-        $value = function ($options) {
-            return new \stdClass();
-        };
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientCluster();
-
-        $option->filter($options, $value);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationThrowsExceptionOnInvalidArguments()
-    {
-        $this->setExpectedException('InvalidArgumentException');
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientCluster();
-
-        $option->filter($options, new \stdClass());
-    }
-}

+ 0 - 138
tests/Predis/Option/ClientConnectionFactoryTest.php

@@ -1,138 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-use Predis\Connection\ConnectionFactory;
-
-/**
- *
- */
-class ClientConnectionFactoryTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testValidationReturnsDefaultFactoryWithSchemeDefinitionsArray()
-    {
-        $connectionClass = get_class($this->getMock('Predis\Connection\SingleConnectionInterface'));
-        $value = array('tcp' => $connectionClass, 'redis' => $connectionClass);
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $default = $this->getMock('Predis\Connection\ConnectionFactoryInterface');
-        $default->expects($this->exactly(2))
-                ->method('define')
-                ->with($this->matchesRegularExpression('/^tcp|redis$/'), $connectionClass);
-
-        $option = $this->getMock('Predis\Option\ClientConnectionFactory', array('getDefault'));
-        $option->expects($this->once())
-               ->method('getDefault')
-               ->with($options)
-               ->will($this->returnValue($default));
-
-        $factory = $option->filter($options, $value);
-
-        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $factory);
-        $this->assertSame($default, $factory);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsFactoryInstancesAsValue()
-    {
-        $value = $this->getMock('Predis\Connection\ConnectionFactoryInterface');
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $option = $this->getMock('Predis\Option\ClientConnectionFactory', array('getDefault'));
-        $option->expects($this->never())->method('getDefault');
-
-        $this->assertSame($value, $option->filter($options, $value));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsCallableObjectAsInitializers()
-    {
-        $value = $this->getMock('Predis\Connection\ConnectionFactoryInterface');
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientConnectionFactory();
-
-        $initializer = $this->getMock('stdClass', array('__invoke'));
-        $initializer->expects($this->once())
-                    ->method('__invoke')
-                    ->with($this->isInstanceOf('Predis\Option\ClientOptionsInterface'), $option)
-                    ->will($this->returnValue($value));
-
-        $cluster = $option->filter($options, $initializer, $option);
-
-        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $cluster);
-        $this->assertSame($value, $cluster);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsStringAsValue()
-    {
-        $factory = 'Predis\Connection\ConnectionFactory';
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $option = $this->getMock('Predis\Option\ClientConnectionFactory', array('getDefault'));
-        $option->expects($this->never())->method('getDefault');
-
-        $this->assertInstanceOf($factory, $option->filter($options, $factory));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationThrowsExceptionOnWrongInvalidArguments()
-    {
-        $this->setExpectedException('InvalidArgumentException');
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientConnectionFactory();
-
-        $option->filter($options, new \stdClass());
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testInvokeReturnsSpecifiedFactoryOrDefault()
-    {
-        $value = $this->getMock('Predis\Connection\ConnectionFactoryInterface');
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $option = $this->getMock('Predis\Option\ClientConnectionFactory', array('filter', 'getDefault'));
-        $option->expects($this->once())
-               ->method('filter')
-               ->with($options, $value)
-               ->will($this->returnValue($value));
-        $option->expects($this->never())->method('getDefault');
-
-        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $option($options, $value));
-
-        $option = $this->getMock('Predis\Option\ClientConnectionFactory', array('filter', 'getDefault'));
-        $option->expects($this->never())->method('filter');
-        $option->expects($this->once())
-               ->method('getDefault')
-               ->with($options)
-               ->will($this->returnValue($value));
-
-        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $option($options, null));
-    }
-}

+ 0 - 31
tests/Predis/Option/ClientExceptionsTest.php

@@ -1,31 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-/**
- *
- */
-class ClientExceptionsTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testDefaultReturnsTrue()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientExceptions();
-
-        $this->assertTrue($option->getDefault($options));
-    }
-}

+ 0 - 128
tests/Predis/Option/ClientOptionsTest.php

@@ -1,128 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-/**
- * @todo We should test the inner work performed by this class
- *       using mock objects, but it is quite hard to to that.
- */
-class ClientOptionsTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testConstructorWithoutArguments()
-    {
-        $options = new ClientOptions();
-
-        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $options->connections);
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $options->profile);
-        $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $options->cluster);
-        $this->assertNull($options->prefix);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testConstructorWithArrayArgument()
-    {
-        $options = new ClientOptions(array(
-            'cluster' => 'Predis\Connection\PredisCluster',
-            'connections' => 'Predis\Connection\ConnectionFactory',
-            'prefix' => 'prefix:',
-            'profile' => '2.0',
-            'exceptions' => false,
-        ));
-
-        $this->assertInstanceOf('Predis\Connection\ConnectionFactoryInterface', $options->connections);
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $options->profile);
-        $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $options->cluster);
-        $this->assertInstanceOf('Predis\Command\Processor\CommandProcessorInterface', $options->prefix);
-        $this->assertInternalType('bool', $options->exceptions);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testHandlesCustomOptionsWithoutHandlers()
-    {
-        $options = new ClientOptions(array(
-            'custom' => 'foobar',
-        ));
-
-        $this->assertSame('foobar', $options->custom);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testIsSetReturnsIfOptionHasBeenSetByUser()
-    {
-        $options = new ClientOptions(array(
-            'prefix' => 'prefix:',
-            'custom' => 'foobar',
-        ));
-
-        $this->assertTrue(isset($options->prefix));
-        $this->assertTrue(isset($options->custom));
-        $this->assertFalse(isset($options->profile));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testGetDefaultUsingOptionName()
-    {
-        $options = new ClientOptions();
-
-        $this->assertInstanceOf('Predis\Connection\PredisCluster', $options->getDefault('cluster'));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testGetDefaultUsingUnhandledOptionName()
-    {
-        $options = new ClientOptions();
-        $option = new ClientCluster();
-
-        $this->assertNull($options->getDefault('foo'));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testGetDefaultUsingOptionInstance()
-    {
-        $options = new ClientOptions();
-        $option = new ClientCluster();
-
-        $this->assertInstanceOf('Predis\Connection\PredisCluster', $options->getDefault($option));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testGetDefaultUsingUnhandledOptionInstance()
-    {
-        $options = new ClientOptions();
-        $option = new CustomOption(array(
-            'default' => function ($options) {
-                return 'foo';
-            },
-        ));
-
-        $this->assertSame('foo', $options->getDefault($option));
-    }
-}

+ 0 - 59
tests/Predis/Option/ClientPrefixTest.php

@@ -1,59 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-/**
- *
- */
-class ClientPrefixTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testValidationReturnsCommandProcessor()
-    {
-        $value = 'prefix:';
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientPrefix();
-
-        $return = $option->filter($options, $value);
-
-        $this->assertInstanceOf('Predis\Command\Processor\CommandProcessorInterface', $return);
-        $this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $return);
-        $this->assertEquals($value, $return->getPrefix());
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testDefaultReturnsNull()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientPrefix();
-
-        $this->assertNull($option->getDefault($options));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testInvokeReturnsCommandProcessorOrNull()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientPrefix();
-
-        $this->assertInstanceOf('Predis\Command\Processor\CommandProcessorInterface', $option($options, 'prefix:'));
-        $this->assertNull($option($options, null));
-    }
-}

+ 0 - 211
tests/Predis/Option/ClientProfileTest.php

@@ -1,211 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-use Predis\Command\Processor\KeyPrefixProcessor;
-use Predis\Profile\ServerProfile;
-
-/**
- *
- */
-class ClientProfileTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testValidationReturnsServerProfileWithStringValue()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientProfile();
-
-        $profile = $option->filter($options, '2.0');
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertEquals('2.0', $profile->getVersion());
-        $this->assertNull($profile->getProcessor());
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsProfileInstancesAsValue()
-    {
-        $value = ServerProfile::get('2.0');
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientProfile();
-
-        $profile = $option->filter($options, $value);
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertEquals('2.0', $profile->getVersion());
-        $this->assertNull($profile->getProcessor());
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsCallableObjectAsInitializers()
-    {
-        $value = $this->getMock('Predis\Profile\ServerProfileInterface');
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientProfile();
-
-        $initializer = $this->getMock('stdClass', array('__invoke'));
-        $initializer->expects($this->once())
-                    ->method('__invoke')
-                    ->with($this->isInstanceOf('Predis\Option\ClientOptionsInterface'), $option)
-                    ->will($this->returnValue($value));
-
-        $profile = $option->filter($options, $initializer, $option);
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertSame($value, $profile);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationThrowsExceptionOnWrongInvalidArguments()
-    {
-        $this->setExpectedException('InvalidArgumentException');
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientProfile();
-
-        $option->filter($options, new \stdClass());
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testDefaultReturnsDefaultServerProfile()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientProfile();
-
-        $profile = $option->getDefault($options);
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile);
-        $this->assertNull($profile->getProcessor());
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testInvokeReturnsSpecifiedServerProfileOrDefault()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientProfile();
-
-        $profile = $option($options, '2.0');
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertEquals('2.0', $profile->getVersion());
-        $this->assertNull($profile->getProcessor());
-
-        $profile = $option($options, null);
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile);
-        $this->assertNull($profile->getProcessor());
-    }
-
-    /**
-     * @group disconnected
-     * @todo Can't we when trap __isset when mocking an interface? Doesn't seem to work here.
-     */
-    public function testFilterSetsPrefixProcessorFromClientOptions()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptions', array('__isset', '__get'));
-        $options->expects($this->once())
-                ->method('__isset')
-                ->with('prefix')
-                ->will($this->returnValue(true));
-        $options->expects($this->once())
-                ->method('__get')
-                ->with('prefix')
-                ->will($this->returnValue(new KeyPrefixProcessor('prefix:')));
-
-        $option = new ClientProfile();
-
-        $profile = $option->filter($options, '2.0');
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertEquals('2.0', $profile->getVersion());
-        $this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $profile->getProcessor());
-        $this->assertEquals('prefix:', $profile->getProcessor()->getPrefix());
-    }
-
-    /**
-     * @group disconnected
-     * @todo Can't we when trap __isset when mocking an interface? Doesn't seem to work here.
-     */
-    public function testDefaultSetsPrefixProcessorFromClientOptions()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptions', array('__isset', '__get'));
-        $options->expects($this->once())
-                ->method('__isset')
-                ->with('prefix')
-                ->will($this->returnValue(true));
-        $options->expects($this->once())
-                ->method('__get')
-                ->with('prefix')
-                ->will($this->returnValue(new KeyPrefixProcessor('prefix:')));
-
-        $option = new ClientProfile();
-
-        $profile = $option->getDefault($options);
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile);
-        $this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $profile->getProcessor());
-        $this->assertEquals('prefix:', $profile->getProcessor()->getPrefix());
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationDoesNotSetPrefixProcessorWhenValueIsProfileInstance()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptions', array('__isset', '__get'));
-        $options->expects($this->never())->method('__isset');
-        $options->expects($this->never())->method('__get');
-
-        $option = new ClientProfile();
-
-        $profile = $option->filter($options, ServerProfile::getDefault());
-
-        $this->assertInstanceOf('Predis\Profile\ServerProfileInterface', $profile);
-        $this->assertNull($profile->getProcessor());
-    }
-
-    /**
-     * @group disconnected
-     * @expectedException InvalidArgumentException
-     * @expectedExceptionMessage Invalid value for the profile option
-     */
-    public function testValidationThrowsExceptionOnInvalidObjectReturnedByCallback()
-    {
-        $value = function ($options) {
-            return new \stdClass();
-        };
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientProfile();
-
-        $option->filter($options, $value);
-    }
-}

+ 0 - 101
tests/Predis/Option/ClientReplicationTest.php

@@ -1,101 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-/**
- *
- */
-class ClientReplicationTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsFQNStringAsInitializer()
-    {
-        $replicationClass = get_class($this->getMock('Predis\Connection\ReplicationConnectionInterface'));
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientReplication();
-
-        $replication = $option->filter($options, $replicationClass);
-
-        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $replication);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsBooleanValue()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientReplication();
-
-        $replication = $option->filter($options, true);
-        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $replication);
-
-        $replication = $option->filter($options, false);
-        $this->assertNull($replication);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testValidationAcceptsCallableObjectAsInitializers()
-    {
-        $value = $this->getMock('Predis\Connection\ReplicationConnectionInterface');
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientReplication();
-
-        $initializer = $this->getMock('stdClass', array('__invoke'));
-        $initializer->expects($this->once())
-                    ->method('__invoke')
-                    ->with($this->isInstanceOf('Predis\Option\ClientOptionsInterface'), $option)
-                    ->will($this->returnValue($value));
-
-        $replication = $option->filter($options, $initializer, $option);
-
-        $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $replication);
-        $this->assertSame($value, $replication);
-    }
-
-    /**
-     * @group disconnected
-     * @expectedException InvalidArgumentException
-     */
-    public function testValidationThrowsExceptionOnInvalidObjectReturnedByCallback()
-    {
-        $value = function ($options) {
-            return new \stdClass();
-        };
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientReplication();
-
-        $option->filter($options, $value);
-    }
-
-    /**
-     * @group disconnected
-     * @expectedException InvalidArgumentException
-     */
-    public function testValidationThrowsExceptionOnInvalidClassTypes()
-    {
-        $connectionClass = get_class($this->getMock('Predis\Connection\SingleConnectionInterface'));
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new ClientReplication();
-
-        $option->filter($options, $connectionClass);
-    }
-}

+ 0 - 114
tests/Predis/Option/CustomOptionTest.php

@@ -1,114 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Option;
-
-use \PHPUnit_Framework_TestCase as StandardTestCase;
-
-/**
- *
- */
-class CustomOptionTest extends StandardTestCase
-{
-    /**
-     * @group disconnected
-     * @expectedException InvalidArgumentException
-     */
-    public function testConstructorAcceptsOnlyCallablesForFilter()
-    {
-        $option = new CustomOption(array('filter' => new \stdClass()));
-    }
-
-    /**
-     * @group disconnected
-     * @expectedException InvalidArgumentException
-     */
-    public function testConstructorAcceptsOnlyCallablesForDefault()
-    {
-        $option = new CustomOption(array('default' => new \stdClass()));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testConstructorIgnoresUnrecognizedParameters()
-    {
-        $option = new CustomOption(array('unknown' => new \stdClass()));
-
-        $this->assertNotNull($option);
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testFilterWithoutCallbackReturnsValue()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new CustomOption();
-
-        $this->assertEquals('test', $option->filter($options, 'test'));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testDefaultWithoutCallbackReturnsNull()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-        $option = new CustomOption();
-
-        $this->assertNull($option->getDefault($options));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testInvokeCallsFilterCallback()
-    {
-        $value = 'test';
-
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $filter = $this->getMock('stdClass', array('__invoke'));
-        $filter->expects($this->once())
-               ->method('__invoke')
-               ->with($this->isInstanceOf('Predis\Option\ClientOptionsInterface'), $value)
-               ->will($this->returnValue(true));
-
-        $default = $this->getMock('stdClass', array('__invoke'));
-        $default->expects($this->never())->method('__invoke');
-
-        $option = new CustomOption(array('filter' => $filter, 'default' => $default));
-
-        $this->assertTrue($option($options, $value));
-    }
-
-    /**
-     * @group disconnected
-     */
-    public function testInvokeCallsDefaultCallback()
-    {
-        $options = $this->getMock('Predis\Option\ClientOptionsInterface');
-
-        $filter = $this->getMock('stdClass', array('__invoke'));
-        $filter->expects($this->never())->method('__invoke');
-
-        $default = $this->getMock('stdClass', array('__invoke'));
-        $default->expects($this->once())
-                ->method('__invoke')
-                ->with($this->isInstanceOf('Predis\Option\ClientOptionsInterface'))
-                ->will($this->returnValue(true));
-
-        $option = new CustomOption(array('filter' => $filter, 'default' => $default));
-
-        $this->assertTrue($option($options, null));
-    }
-}