Эх сурвалжийг харах

Merge branch 'v0.9/client-options'

Daniele Alessandri 11 жил өмнө
parent
commit
089b972def
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)
 v0.8.5 (2013-xx-xx)
 ===============================================================================
 ===============================================================================
 
 

+ 13 - 12
lib/Predis/Client.php

@@ -11,14 +11,15 @@
 
 
 namespace Predis;
 namespace Predis;
 
 
+use InvalidArgumentException;
 use Predis\Command\CommandInterface;
 use Predis\Command\CommandInterface;
 use Predis\Command\ScriptedCommand;
 use Predis\Command\ScriptedCommand;
+use Predis\Configuration\Options;
+use Predis\Configuration\OptionsInterface;
 use Predis\Connection\AggregatedConnectionInterface;
 use Predis\Connection\AggregatedConnectionInterface;
 use Predis\Connection\ConnectionInterface;
 use Predis\Connection\ConnectionInterface;
 use Predis\Connection\ConnectionFactoryInterface;
 use Predis\Connection\ConnectionFactoryInterface;
 use Predis\Monitor\MonitorContext;
 use Predis\Monitor\MonitorContext;
-use Predis\Option\ClientOptions;
-use Predis\Option\ClientOptionsInterface;
 use Predis\Pipeline\PipelineContext;
 use Predis\Pipeline\PipelineContext;
 use Predis\Profile\ServerProfile;
 use Predis\Profile\ServerProfile;
 use Predis\PubSub\PubSubContext;
 use Predis\PubSub\PubSubContext;
@@ -45,34 +46,34 @@ class Client implements ClientInterface
      */
      */
     public function __construct($parameters = null, $options = null)
     public function __construct($parameters = null, $options = null)
     {
     {
-        $this->options = $this->filterOptions($options);
+        $this->options = $this->createOptions($options);
         $this->profile = $this->options->profile;
         $this->profile = $this->options->profile;
         $this->connection = $this->initializeConnection($parameters);
         $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.
      * @param mixed $options Client options.
-     * @return ClientOptions
+     * @return OptionsInterface
      */
      */
-    protected function filterOptions($options)
+    protected function createOptions($options)
     {
     {
         if (!isset($options)) {
         if (!isset($options)) {
-            return new ClientOptions();
+            return new Options();
         }
         }
 
 
         if (is_array($options)) {
         if (is_array($options)) {
-            return new ClientOptions($options);
+            return new Options($options);
         }
         }
 
 
-        if ($options instanceof ClientOptionsInterface) {
+        if ($options instanceof OptionsInterface) {
             return $options;
             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;
 namespace Predis;
 
 
+use Predis\Configuration\OptionsInterface;
 use Predis\Connection\ConnectionInterface;
 use Predis\Connection\ConnectionInterface;
-use Predis\Option\ClientOptionsInterface;
 use Predis\Profile\ServerProfileInterface;
 use Predis\Profile\ServerProfileInterface;
 
 
 /**
 /**
@@ -34,7 +34,7 @@ interface ClientInterface extends BasicClientInterface
     /**
     /**
      * Returns the client options specified upon initialization.
      * Returns the client options specified upon initialization.
      *
      *
-     * @return ClientOptionsInterface
+     * @return OptionsInterface
      */
      */
     public function getOptions();
     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.
  * 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>
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
  */
-class ClientExceptions extends AbstractOption
+class ExceptionsOption implements OptionInterface
 {
 {
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */
-    public function filter(ClientOptionsInterface $options, $value)
+    public function filter(OptionsInterface $options, $value)
     {
     {
-        return (bool) $value;
+        return filter_var($value, FILTER_VALIDATE_BOOLEAN);
     }
     }
 
 
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */
-    public function getDefault(ClientOptionsInterface $options)
+    public function getDefault(OptionsInterface $options)
     {
     {
         return true;
         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.
  * file that was distributed with this source code.
  */
  */
 
 
-namespace Predis\Option;
+namespace Predis\Configuration;
 
 
 use Predis\Command\Processor\KeyPrefixProcessor;
 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>
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
  */
-class ClientPrefix extends AbstractOption
+class PrefixOption implements OptionInterface
 {
 {
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */
-    public function filter(ClientOptionsInterface $options, $value)
+    public function filter(OptionsInterface $options, $value)
     {
     {
         return new KeyPrefixProcessor($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 = $this->getMock('stdClass', array('__invoke'));
         $callable->expects($this->once())
         $callable->expects($this->once())
                  ->method('__invoke')
                  ->method('__invoke')
-                 ->with($this->isInstanceOf('Predis\Option\ClientOptions'))
+                 ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
                  ->will($this->returnValue($connection));
                  ->will($this->returnValue($connection));
 
 
         $client = new Client($callable);
         $client = new Client($callable);
@@ -227,7 +227,7 @@ class ClientTest extends StandardTestCase
         $callable = $this->getMock('stdClass', array('__invoke'));
         $callable = $this->getMock('stdClass', array('__invoke'));
         $callable->expects($this->once())
         $callable->expects($this->once())
                  ->method('__invoke')
                  ->method('__invoke')
-                 ->with($this->isInstanceOf('Predis\Option\ClientOptions'))
+                 ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
                  ->will($this->returnValue($wrongType));
                  ->will($this->returnValue($wrongType));
 
 
         $client = new Client($callable);
         $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));
-    }
-}