From 371ac917777ddd6e0fc6eb672df0dfd0e175deb1 Mon Sep 17 00:00:00 2001 From: Daniele Alessandri Date: Sat, 3 Dec 2011 09:57:09 +0100 Subject: [PATCH] [tests] Rewrite the whole test suite to allow more granular testing. Fix also a few bugs found while rewriting the test suite. In order to be able to run integration tests, the test suite requires a version of Redis >= 2.4.0. The units have been splitted into several different groups using PHPUnit @group annotation to allow developers to enable, disable and combine certain types of tests. The available groups are: - disconnected: can run without a Redis server online - connected: active connection to a Redis server is required - commands: test dedicated to a specific Redis command - slow: performs operations that can slow down execution; A list of the available groups can be obtained by running phpunit --list-groups Groups of tests can be disabled or enabled via the XML configuration file or the standard command-line test runner. Please note that due to a bug in PHPUnit, older versions ignore the --group option when the group is excluded in the XML configuration file. Please refer to http://github.com/sebastianbergmann/phpunit/issues/320 for details Integration tests in the @connected group check if the command being tested is defined in the selected server profile (see the value of the TEST_SERVER_VERSION constant in phpunit.xml). If the command is not defined in the target server profile, the integration test is automatically marked as skipped. We also provide an helper script in the bin directory that can be used to automatically generate a file with the scheleton of a test case for a Redis command by specifying the name of the class in the Predis\Commands namespace. For example, to generate a test case for SET (represented by the Predis\Commands\StringSet class): ./bin/generate-command-test.php --class=StringSet The realm of a command is automatically inferred from the name of the class, but it can be set using the --realm option. --- .gitignore | 1 - .travis.yml | 3 +- README.md | 33 +- TODO | 8 - bin/generate-command-test.php | 237 ++ examples/ServerSideScripting.php | 2 +- lib/Predis/Autoloader.php | 7 +- lib/Predis/Client.php | 6 +- lib/Predis/Commands/HashDelete.php | 8 - lib/Predis/Commands/KeyKeysV12x.php | 1 + lib/Predis/Commands/KeyRandom.php | 2 +- lib/Predis/Commands/ListPopFirstBlocking.php | 12 + lib/Predis/Commands/PrefixHelpers.php | 12 +- lib/Predis/Commands/PrefixableCommand.php | 7 +- .../Commands/Processors/ProcessorChain.php | 3 +- lib/Predis/Commands/PubSubUnsubscribe.php | 10 + lib/Predis/Commands/ScriptedCommand.php | 20 +- lib/Predis/Commands/ServerEval.php | 2 +- lib/Predis/Commands/ServerInfo.php | 2 +- lib/Predis/Commands/ServerInfoV26x.php | 6 +- lib/Predis/Commands/SetAdd.php | 8 - lib/Predis/Commands/SetRemove.php | 8 - lib/Predis/Commands/ZSetAdd.php | 18 +- lib/Predis/Commands/ZSetRemove.php | 8 - .../Iterators/MultiBulkResponseSimple.php | 2 +- .../Iterators/MultiBulkResponseTuple.php | 12 +- lib/Predis/MonitorContext.php | 8 +- lib/Predis/Network/ConnectionBase.php | 7 +- lib/Predis/Network/PhpiredisConnection.php | 9 +- lib/Predis/Network/PredisCluster.php | 14 +- lib/Predis/Network/StreamConnection.php | 1 + lib/Predis/Network/WebdisConnection.php | 18 +- lib/Predis/NotSupportedException.php | 22 + lib/Predis/Options/ClientCluster.php | 12 +- .../Options/ClientConnectionFactory.php | 8 + lib/Predis/Options/CustomOption.php | 2 +- lib/Predis/Pipeline/PipelineContext.php | 16 +- lib/Predis/Profiles/ServerProfile.php | 26 +- lib/Predis/Profiles/ServerVersion12.php | 146 +- lib/Predis/Profiles/ServerVersion20.php | 210 +- lib/Predis/Profiles/ServerVersion22.php | 240 +- lib/Predis/Profiles/ServerVersion24.php | 242 +- lib/Predis/Profiles/ServerVersionNext.php | 20 +- lib/Predis/PubSub/DispatcherLoop.php | 3 +- lib/Predis/PubSub/PubSubContext.php | 38 +- lib/Predis/Transaction/MultiExecContext.php | 32 +- phpunit.xml.dist | 29 +- test/ClientFeaturesTest.php | 830 ------- test/PredisShared.php | 283 --- test/RedisCommandsTest.php | 2181 ----------------- .../PHPUnit/ArrayHasSameValuesConstraint.php | 52 + tests/PHPUnit/CommandTestCase.php | 174 ++ tests/PHPUnit/ConnectionTestCase.php | 387 +++ .../PHPUnit/DistributionStrategyTestCase.php | 67 + tests/PHPUnit/ServerVersionTestCase.php | 77 + tests/Predis/ClientExceptionTest.php | 43 + tests/Predis/ClientTest.php | 647 +++++ tests/Predis/Commands/CommandTest.php | 216 ++ tests/Predis/Commands/ConnectionAuthTest.php | 64 + tests/Predis/Commands/ConnectionEchoTest.php | 76 + tests/Predis/Commands/ConnectionPingTest.php | 71 + tests/Predis/Commands/ConnectionQuitTest.php | 72 + .../Predis/Commands/ConnectionSelectTest.php | 86 + tests/Predis/Commands/HashDeleteTest.php | 114 + tests/Predis/Commands/HashExistsTest.php | 103 + tests/Predis/Commands/HashGetAllTest.php | 104 + tests/Predis/Commands/HashGetMultipleTest.php | 120 + tests/Predis/Commands/HashGetTest.php | 100 + .../Commands/HashIncrementByFloatTest.php | 125 + tests/Predis/Commands/HashIncrementByTest.php | 125 + tests/Predis/Commands/HashKeysTest.php | 104 + tests/Predis/Commands/HashLengthTest.php | 99 + tests/Predis/Commands/HashSetMultipleTest.php | 126 + tests/Predis/Commands/HashSetPreserveTest.php | 103 + tests/Predis/Commands/HashSetTest.php | 102 + tests/Predis/Commands/HashValuesTest.php | 104 + tests/Predis/Commands/KeyDeleteTest.php | 108 + tests/Predis/Commands/KeyExistsTest.php | 97 + tests/Predis/Commands/KeyExpireAtTest.php | 119 + tests/Predis/Commands/KeyExpireTest.php | 132 + tests/Predis/Commands/KeyKeysTest.php | 94 + tests/Predis/Commands/KeyKeysV12xTest.php | 80 + tests/Predis/Commands/KeyMoveTest.php | 110 + tests/Predis/Commands/KeyPersistTest.php | 112 + .../Commands/KeyPreciseExpireAtTest.php | 109 + .../Predis/Commands/KeyPreciseExpireTest.php | 134 + .../Commands/KeyPreciseTimeToLiveTest.php | 109 + tests/Predis/Commands/KeyRandomTest.php | 87 + .../Predis/Commands/KeyRenamePreserveTest.php | 100 + tests/Predis/Commands/KeyRenameTest.php | 99 + tests/Predis/Commands/KeySortTest.php | 270 ++ tests/Predis/Commands/KeyTimeToLiveTest.php | 109 + tests/Predis/Commands/KeyTypeTest.php | 98 + tests/Predis/Commands/ListIndexTest.php | 115 + tests/Predis/Commands/ListInsertTest.php | 123 + tests/Predis/Commands/ListLengthTest.php | 110 + .../Commands/ListPopFirstBlockingTest.php | 94 + tests/Predis/Commands/ListPopFirstTest.php | 110 + .../Commands/ListPopLastBlockingTest.php | 94 + .../ListPopLastPushHeadBlockingTest.php | 75 + .../Commands/ListPopLastPushHeadTest.php | 144 ++ tests/Predis/Commands/ListPopLastTest.php | 110 + tests/Predis/Commands/ListPushHeadTest.php | 113 + tests/Predis/Commands/ListPushHeadXTest.php | 111 + tests/Predis/Commands/ListPushTailTest.php | 113 + tests/Predis/Commands/ListPushTailXTest.php | 111 + tests/Predis/Commands/ListRangeTest.php | 154 ++ tests/Predis/Commands/ListRemoveTest.php | 138 ++ tests/Predis/Commands/ListSetTest.php | 112 + tests/Predis/Commands/ListTrimTest.php | 144 ++ tests/Predis/Commands/PrefixHelpersTest.php | 84 + .../Predis/Commands/PrefixableCommandTest.php | 54 + .../Processors/KeyPrefixProcessorTest.php | 83 + .../Processors/ProcessorChainTest.php | 170 ++ tests/Predis/Commands/PubSubPublishTest.php | 87 + .../Commands/PubSubSubscribeByPatternTest.php | 173 ++ tests/Predis/Commands/PubSubSubscribeTest.php | 173 ++ .../PubSubUnsubscribeByPatternTest.php | 141 ++ .../Predis/Commands/PubSubUnsubscribeTest.php | 139 ++ tests/Predis/Commands/ScriptedCommandTest.php | 101 + .../ServerBackgroundRewriteAOFTest.php | 56 + .../Commands/ServerBackgroundSaveTest.php | 56 + tests/Predis/Commands/ServerClientTest.php | 142 ++ tests/Predis/Commands/ServerConfigTest.php | 173 ++ .../Commands/ServerDatabaseSizeTest.php | 67 + tests/Predis/Commands/ServerEvalSHATest.php | 118 + tests/Predis/Commands/ServerEvalTest.php | 122 + tests/Predis/Commands/ServerFlushAllTest.php | 56 + .../Commands/ServerFlushDatabaseTest.php | 69 + tests/Predis/Commands/ServerInfoTest.php | 289 +++ tests/Predis/Commands/ServerInfoV26xTest.php | 307 +++ tests/Predis/Commands/ServerLastSaveTest.php | 66 + tests/Predis/Commands/ServerMonitorTest.php | 69 + tests/Predis/Commands/ServerObjectTest.php | 115 + tests/Predis/Commands/ServerSaveTest.php | 56 + tests/Predis/Commands/ServerScriptTest.php | 110 + tests/Predis/Commands/ServerShutdownTest.php | 48 + tests/Predis/Commands/ServerSlaveOfTest.php | 87 + tests/Predis/Commands/ServerSlowlogTest.php | 119 + tests/Predis/Commands/SetAddTest.php | 112 + tests/Predis/Commands/SetCardinalityTest.php | 108 + .../Commands/SetDifferenceStoreTest.php | 131 + tests/Predis/Commands/SetDifferenceTest.php | 133 + .../Commands/SetIntersectionStoreTest.php | 144 ++ tests/Predis/Commands/SetIntersectionTest.php | 144 ++ tests/Predis/Commands/SetIsMemberTest.php | 112 + tests/Predis/Commands/SetMembersTest.php | 104 + tests/Predis/Commands/SetMoveTest.php | 120 + tests/Predis/Commands/SetPopTest.php | 101 + tests/Predis/Commands/SetRandomMemberTest.php | 109 + tests/Predis/Commands/SetRemoveTest.php | 116 + tests/Predis/Commands/SetUnionStoreTest.php | 131 + tests/Predis/Commands/SetUnionTest.php | 133 + tests/Predis/Commands/StringAppendTest.php | 111 + .../Predis/Commands/StringDecrementByTest.php | 136 + tests/Predis/Commands/StringDecrementTest.php | 123 + tests/Predis/Commands/StringGetBitTest.php | 129 + .../Predis/Commands/StringGetMultipleTest.php | 127 + tests/Predis/Commands/StringGetRangeTest.php | 114 + tests/Predis/Commands/StringGetSetTest.php | 100 + tests/Predis/Commands/StringGetTest.php | 121 + .../Commands/StringIncrementByFloatTest.php | 136 + .../Predis/Commands/StringIncrementByTest.php | 136 + tests/Predis/Commands/StringIncrementTest.php | 110 + .../Commands/StringPreciseSetExpireTest.php | 130 + tests/Predis/Commands/StringSetBitTest.php | 145 ++ tests/Predis/Commands/StringSetExpireTest.php | 128 + .../StringSetMultiplePreserveTest.php | 113 + .../Predis/Commands/StringSetMultipleTest.php | 99 + tests/Predis/Commands/StringSetRangeTest.php | 139 ++ tests/Predis/Commands/StringSetTest.php | 85 + tests/Predis/Commands/StringStrlenTest.php | 110 + tests/Predis/Commands/StringSubstrTest.php | 77 + .../Commands/TransactionDiscardTest.php | 82 + tests/Predis/Commands/TransactionExecTest.php | 114 + .../Predis/Commands/TransactionMultiTest.php | 93 + .../Commands/TransactionUnwatchTest.php | 86 + .../Predis/Commands/TransactionWatchTest.php | 134 + tests/Predis/Commands/ZSetAddTest.php | 125 + tests/Predis/Commands/ZSetCardinalityTest.php | 99 + tests/Predis/Commands/ZSetCountTest.php | 132 + tests/Predis/Commands/ZSetIncrementByTest.php | 99 + .../Commands/ZSetIntersectionStoreTest.php | 193 ++ .../Predis/Commands/ZSetRangeByScoreTest.php | 230 ++ tests/Predis/Commands/ZSetRangeTest.php | 153 ++ tests/Predis/Commands/ZSetRankTest.php | 102 + .../Commands/ZSetRemoveRangeByRankTest.php | 114 + .../Commands/ZSetRemoveRangeByScoreTest.php | 114 + tests/Predis/Commands/ZSetRemoveTest.php | 101 + .../Commands/ZSetReverseRangeByScoreTest.php | 230 ++ .../Predis/Commands/ZSetReverseRangeTest.php | 153 ++ tests/Predis/Commands/ZSetReverseRankTest.php | 102 + tests/Predis/Commands/ZSetScoreTest.php | 102 + tests/Predis/Commands/ZSetUnionStoreTest.php | 210 ++ tests/Predis/CommunicationExceptionTest.php | 98 + tests/Predis/ConnectionFactoryTest.php | 353 +++ tests/Predis/ConnectionParametersTest.php | 225 ++ .../Distribution/EmptyRingExceptionTest.php | 31 + tests/Predis/Distribution/HashRingTest.php | 132 + .../Distribution/KetamaPureRingTest.php | 133 + tests/Predis/HelpersTest.php | 96 + .../Iterators/MultiBulkResponseSimpleTest.php | 123 + .../Iterators/MultiBulkResponseTupleTest.php | 94 + tests/Predis/MonitorContextTest.php | 171 ++ .../Network/ConnectionExceptionTest.php | 31 + .../Network/PhpiredisConnectionTest.php | 117 + tests/Predis/Network/PredisClusterTest.php | 311 +++ tests/Predis/Network/StreamConnectionTest.php | 111 + tests/Predis/Network/WebdisConnectionTest.php | 198 ++ tests/Predis/Options/ClientClusterTest.php | 125 + .../Options/ClientConnectionFactoryTest.php | 117 + tests/Predis/Options/ClientOptionsTest.php | 79 + tests/Predis/Options/ClientPrefixTest.php | 59 + tests/Predis/Options/ClientProfileTest.php | 172 ++ tests/Predis/Options/CustomOptionTest.php | 114 + tests/Predis/Options/OptionTest.php | 79 + tests/Predis/Pipeline/PipelineContextTest.php | 420 ++++ tests/Predis/PredisExceptionTest.php | 33 + tests/Predis/Profiles/ServerProfileTest.php | 265 ++ tests/Predis/Profiles/ServerVersion12Test.php | 116 + tests/Predis/Profiles/ServerVersion20Test.php | 148 ++ tests/Predis/Profiles/ServerVersion22Test.php | 163 ++ tests/Predis/Profiles/ServerVersion24Test.php | 164 ++ .../Predis/Profiles/ServerVersionNextTest.php | 173 ++ .../Predis/Protocol/ProtocolExceptionTest.php | 31 + tests/Predis/PubSub/DispatcherLoopTest.php | 83 + tests/Predis/PubSub/PubSubContextTest.php | 294 +++ tests/Predis/ResponseErrorTest.php | 63 + tests/Predis/ResponseQueuedTest.php | 51 + tests/Predis/ServerExceptionTest.php | 69 + .../AbortedMultiExecExceptionTest.php | 36 + .../Transaction/MultiExecContextTest.php | 726 ++++++ tests/README.md | 88 + {test => tests}/bootstrap.php | 7 +- 234 files changed, 24387 insertions(+), 3911 deletions(-) create mode 100755 bin/generate-command-test.php create mode 100644 lib/Predis/NotSupportedException.php delete mode 100644 test/ClientFeaturesTest.php delete mode 100644 test/PredisShared.php delete mode 100644 test/RedisCommandsTest.php create mode 100644 tests/PHPUnit/ArrayHasSameValuesConstraint.php create mode 100644 tests/PHPUnit/CommandTestCase.php create mode 100644 tests/PHPUnit/ConnectionTestCase.php create mode 100644 tests/PHPUnit/DistributionStrategyTestCase.php create mode 100644 tests/PHPUnit/ServerVersionTestCase.php create mode 100644 tests/Predis/ClientExceptionTest.php create mode 100644 tests/Predis/ClientTest.php create mode 100644 tests/Predis/Commands/CommandTest.php create mode 100644 tests/Predis/Commands/ConnectionAuthTest.php create mode 100644 tests/Predis/Commands/ConnectionEchoTest.php create mode 100644 tests/Predis/Commands/ConnectionPingTest.php create mode 100644 tests/Predis/Commands/ConnectionQuitTest.php create mode 100644 tests/Predis/Commands/ConnectionSelectTest.php create mode 100644 tests/Predis/Commands/HashDeleteTest.php create mode 100644 tests/Predis/Commands/HashExistsTest.php create mode 100644 tests/Predis/Commands/HashGetAllTest.php create mode 100644 tests/Predis/Commands/HashGetMultipleTest.php create mode 100644 tests/Predis/Commands/HashGetTest.php create mode 100644 tests/Predis/Commands/HashIncrementByFloatTest.php create mode 100644 tests/Predis/Commands/HashIncrementByTest.php create mode 100644 tests/Predis/Commands/HashKeysTest.php create mode 100644 tests/Predis/Commands/HashLengthTest.php create mode 100644 tests/Predis/Commands/HashSetMultipleTest.php create mode 100644 tests/Predis/Commands/HashSetPreserveTest.php create mode 100644 tests/Predis/Commands/HashSetTest.php create mode 100644 tests/Predis/Commands/HashValuesTest.php create mode 100644 tests/Predis/Commands/KeyDeleteTest.php create mode 100644 tests/Predis/Commands/KeyExistsTest.php create mode 100644 tests/Predis/Commands/KeyExpireAtTest.php create mode 100644 tests/Predis/Commands/KeyExpireTest.php create mode 100644 tests/Predis/Commands/KeyKeysTest.php create mode 100644 tests/Predis/Commands/KeyKeysV12xTest.php create mode 100644 tests/Predis/Commands/KeyMoveTest.php create mode 100644 tests/Predis/Commands/KeyPersistTest.php create mode 100644 tests/Predis/Commands/KeyPreciseExpireAtTest.php create mode 100644 tests/Predis/Commands/KeyPreciseExpireTest.php create mode 100644 tests/Predis/Commands/KeyPreciseTimeToLiveTest.php create mode 100644 tests/Predis/Commands/KeyRandomTest.php create mode 100644 tests/Predis/Commands/KeyRenamePreserveTest.php create mode 100644 tests/Predis/Commands/KeyRenameTest.php create mode 100644 tests/Predis/Commands/KeySortTest.php create mode 100644 tests/Predis/Commands/KeyTimeToLiveTest.php create mode 100644 tests/Predis/Commands/KeyTypeTest.php create mode 100644 tests/Predis/Commands/ListIndexTest.php create mode 100644 tests/Predis/Commands/ListInsertTest.php create mode 100644 tests/Predis/Commands/ListLengthTest.php create mode 100644 tests/Predis/Commands/ListPopFirstBlockingTest.php create mode 100644 tests/Predis/Commands/ListPopFirstTest.php create mode 100644 tests/Predis/Commands/ListPopLastBlockingTest.php create mode 100644 tests/Predis/Commands/ListPopLastPushHeadBlockingTest.php create mode 100644 tests/Predis/Commands/ListPopLastPushHeadTest.php create mode 100644 tests/Predis/Commands/ListPopLastTest.php create mode 100644 tests/Predis/Commands/ListPushHeadTest.php create mode 100644 tests/Predis/Commands/ListPushHeadXTest.php create mode 100644 tests/Predis/Commands/ListPushTailTest.php create mode 100644 tests/Predis/Commands/ListPushTailXTest.php create mode 100644 tests/Predis/Commands/ListRangeTest.php create mode 100644 tests/Predis/Commands/ListRemoveTest.php create mode 100644 tests/Predis/Commands/ListSetTest.php create mode 100644 tests/Predis/Commands/ListTrimTest.php create mode 100644 tests/Predis/Commands/PrefixHelpersTest.php create mode 100644 tests/Predis/Commands/PrefixableCommandTest.php create mode 100644 tests/Predis/Commands/Processors/KeyPrefixProcessorTest.php create mode 100644 tests/Predis/Commands/Processors/ProcessorChainTest.php create mode 100644 tests/Predis/Commands/PubSubPublishTest.php create mode 100644 tests/Predis/Commands/PubSubSubscribeByPatternTest.php create mode 100644 tests/Predis/Commands/PubSubSubscribeTest.php create mode 100644 tests/Predis/Commands/PubSubUnsubscribeByPatternTest.php create mode 100644 tests/Predis/Commands/PubSubUnsubscribeTest.php create mode 100644 tests/Predis/Commands/ScriptedCommandTest.php create mode 100644 tests/Predis/Commands/ServerBackgroundRewriteAOFTest.php create mode 100644 tests/Predis/Commands/ServerBackgroundSaveTest.php create mode 100644 tests/Predis/Commands/ServerClientTest.php create mode 100644 tests/Predis/Commands/ServerConfigTest.php create mode 100644 tests/Predis/Commands/ServerDatabaseSizeTest.php create mode 100644 tests/Predis/Commands/ServerEvalSHATest.php create mode 100644 tests/Predis/Commands/ServerEvalTest.php create mode 100644 tests/Predis/Commands/ServerFlushAllTest.php create mode 100644 tests/Predis/Commands/ServerFlushDatabaseTest.php create mode 100644 tests/Predis/Commands/ServerInfoTest.php create mode 100644 tests/Predis/Commands/ServerInfoV26xTest.php create mode 100644 tests/Predis/Commands/ServerLastSaveTest.php create mode 100644 tests/Predis/Commands/ServerMonitorTest.php create mode 100644 tests/Predis/Commands/ServerObjectTest.php create mode 100644 tests/Predis/Commands/ServerSaveTest.php create mode 100644 tests/Predis/Commands/ServerScriptTest.php create mode 100644 tests/Predis/Commands/ServerShutdownTest.php create mode 100644 tests/Predis/Commands/ServerSlaveOfTest.php create mode 100644 tests/Predis/Commands/ServerSlowlogTest.php create mode 100644 tests/Predis/Commands/SetAddTest.php create mode 100644 tests/Predis/Commands/SetCardinalityTest.php create mode 100644 tests/Predis/Commands/SetDifferenceStoreTest.php create mode 100644 tests/Predis/Commands/SetDifferenceTest.php create mode 100644 tests/Predis/Commands/SetIntersectionStoreTest.php create mode 100644 tests/Predis/Commands/SetIntersectionTest.php create mode 100644 tests/Predis/Commands/SetIsMemberTest.php create mode 100644 tests/Predis/Commands/SetMembersTest.php create mode 100644 tests/Predis/Commands/SetMoveTest.php create mode 100644 tests/Predis/Commands/SetPopTest.php create mode 100644 tests/Predis/Commands/SetRandomMemberTest.php create mode 100644 tests/Predis/Commands/SetRemoveTest.php create mode 100644 tests/Predis/Commands/SetUnionStoreTest.php create mode 100644 tests/Predis/Commands/SetUnionTest.php create mode 100644 tests/Predis/Commands/StringAppendTest.php create mode 100644 tests/Predis/Commands/StringDecrementByTest.php create mode 100644 tests/Predis/Commands/StringDecrementTest.php create mode 100644 tests/Predis/Commands/StringGetBitTest.php create mode 100644 tests/Predis/Commands/StringGetMultipleTest.php create mode 100644 tests/Predis/Commands/StringGetRangeTest.php create mode 100644 tests/Predis/Commands/StringGetSetTest.php create mode 100644 tests/Predis/Commands/StringGetTest.php create mode 100644 tests/Predis/Commands/StringIncrementByFloatTest.php create mode 100644 tests/Predis/Commands/StringIncrementByTest.php create mode 100644 tests/Predis/Commands/StringIncrementTest.php create mode 100644 tests/Predis/Commands/StringPreciseSetExpireTest.php create mode 100644 tests/Predis/Commands/StringSetBitTest.php create mode 100644 tests/Predis/Commands/StringSetExpireTest.php create mode 100644 tests/Predis/Commands/StringSetMultiplePreserveTest.php create mode 100644 tests/Predis/Commands/StringSetMultipleTest.php create mode 100644 tests/Predis/Commands/StringSetRangeTest.php create mode 100644 tests/Predis/Commands/StringSetTest.php create mode 100644 tests/Predis/Commands/StringStrlenTest.php create mode 100644 tests/Predis/Commands/StringSubstrTest.php create mode 100644 tests/Predis/Commands/TransactionDiscardTest.php create mode 100644 tests/Predis/Commands/TransactionExecTest.php create mode 100644 tests/Predis/Commands/TransactionMultiTest.php create mode 100644 tests/Predis/Commands/TransactionUnwatchTest.php create mode 100644 tests/Predis/Commands/TransactionWatchTest.php create mode 100644 tests/Predis/Commands/ZSetAddTest.php create mode 100644 tests/Predis/Commands/ZSetCardinalityTest.php create mode 100644 tests/Predis/Commands/ZSetCountTest.php create mode 100644 tests/Predis/Commands/ZSetIncrementByTest.php create mode 100644 tests/Predis/Commands/ZSetIntersectionStoreTest.php create mode 100644 tests/Predis/Commands/ZSetRangeByScoreTest.php create mode 100644 tests/Predis/Commands/ZSetRangeTest.php create mode 100644 tests/Predis/Commands/ZSetRankTest.php create mode 100644 tests/Predis/Commands/ZSetRemoveRangeByRankTest.php create mode 100644 tests/Predis/Commands/ZSetRemoveRangeByScoreTest.php create mode 100644 tests/Predis/Commands/ZSetRemoveTest.php create mode 100644 tests/Predis/Commands/ZSetReverseRangeByScoreTest.php create mode 100644 tests/Predis/Commands/ZSetReverseRangeTest.php create mode 100644 tests/Predis/Commands/ZSetReverseRankTest.php create mode 100644 tests/Predis/Commands/ZSetScoreTest.php create mode 100644 tests/Predis/Commands/ZSetUnionStoreTest.php create mode 100644 tests/Predis/CommunicationExceptionTest.php create mode 100644 tests/Predis/ConnectionFactoryTest.php create mode 100644 tests/Predis/ConnectionParametersTest.php create mode 100644 tests/Predis/Distribution/EmptyRingExceptionTest.php create mode 100644 tests/Predis/Distribution/HashRingTest.php create mode 100644 tests/Predis/Distribution/KetamaPureRingTest.php create mode 100644 tests/Predis/HelpersTest.php create mode 100644 tests/Predis/Iterators/MultiBulkResponseSimpleTest.php create mode 100644 tests/Predis/Iterators/MultiBulkResponseTupleTest.php create mode 100644 tests/Predis/MonitorContextTest.php create mode 100644 tests/Predis/Network/ConnectionExceptionTest.php create mode 100644 tests/Predis/Network/PhpiredisConnectionTest.php create mode 100644 tests/Predis/Network/PredisClusterTest.php create mode 100644 tests/Predis/Network/StreamConnectionTest.php create mode 100644 tests/Predis/Network/WebdisConnectionTest.php create mode 100644 tests/Predis/Options/ClientClusterTest.php create mode 100644 tests/Predis/Options/ClientConnectionFactoryTest.php create mode 100644 tests/Predis/Options/ClientOptionsTest.php create mode 100644 tests/Predis/Options/ClientPrefixTest.php create mode 100644 tests/Predis/Options/ClientProfileTest.php create mode 100644 tests/Predis/Options/CustomOptionTest.php create mode 100644 tests/Predis/Options/OptionTest.php create mode 100644 tests/Predis/Pipeline/PipelineContextTest.php create mode 100644 tests/Predis/PredisExceptionTest.php create mode 100644 tests/Predis/Profiles/ServerProfileTest.php create mode 100644 tests/Predis/Profiles/ServerVersion12Test.php create mode 100644 tests/Predis/Profiles/ServerVersion20Test.php create mode 100644 tests/Predis/Profiles/ServerVersion22Test.php create mode 100644 tests/Predis/Profiles/ServerVersion24Test.php create mode 100644 tests/Predis/Profiles/ServerVersionNextTest.php create mode 100644 tests/Predis/Protocol/ProtocolExceptionTest.php create mode 100644 tests/Predis/PubSub/DispatcherLoopTest.php create mode 100644 tests/Predis/PubSub/PubSubContextTest.php create mode 100644 tests/Predis/ResponseErrorTest.php create mode 100644 tests/Predis/ResponseQueuedTest.php create mode 100644 tests/Predis/ServerExceptionTest.php create mode 100644 tests/Predis/Transaction/AbortedMultiExecExceptionTest.php create mode 100644 tests/Predis/Transaction/MultiExecContextTest.php create mode 100644 tests/README.md rename {test => tests}/bootstrap.php (50%) diff --git a/.gitignore b/.gitignore index 8a7575c5..cc9b4e00 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ phpunit.xml experiments/ -test/enable.tests diff --git a/.travis.yml b/.travis.yml index c28c4bad..0fc69047 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,7 @@ language: php php: - 5.3 - 5.4 -before_script: touch test/enable.tests branches: only: - master - - version-0.6 + - v0.7 diff --git a/README.md b/README.md index 8b3f60bd..43b21fc4 100644 --- a/README.md +++ b/README.md @@ -148,27 +148,40 @@ $redis->newcmd(); ``` -## Development ## +## Test suite ## -Predis is fully backed up by a test suite which tries to cover all the aspects of the -client library and the interaction of every single command with a Redis server. If you -want to work on Predis, it is highly recommended that you first run the test suite to -be sure that everything is OK, and report strange behaviours or bugs. +__ATTENTION__: Do not run the test suite shipped with Predis against instances of +Redis running in production environments or containing data you are interested in! -When modifying Predis please be sure that no warnings or notices are emitted by PHP +Predis has a comprehensive test suite covering every aspect of the library. The suite +performs integration tests against a running instance of Redis (>= 2.4.0 is required) +to verify the correct behaviour of the implementation of each command and automatically +skips commands that are not defined in the selected version of Redis. If you do not have +Redis up and running, integration tests can be disabled. By default, the test suite is +configured to execute integration tests using the server profile for Redis v2.4 (which +is the current stable version of Redis). You can optionally run the suite against a +Redis instance built from the `unstable` branch with the development profile by changing +the `TEST_SERVER_VERSION` to `dev` in the `phpunit.xml` file. More details about testing +Predis are available in `tests/README.md`. + +## Contributing ## + +If you want to work on Predis, it is highly recommended that you first run the test +suite in order to check that everything is OK, and report strange behaviours or bugs. + +When modifying Predis please make sure that no warnings or notices are emitted by PHP by running the interpreter in your development environment with the `error_reporting` variable set to `E_ALL | E_STRICT`. The recommended way to contribute to Predis is to fork the project on GitHub, create new topic branches on your newly created repository to fix or add features and then -open a new pull request with a description of the applied changes. Obviously, you can -use any other Git hosting provider of your preference. Diff patches will be accepted -too, even though they are not the preferred way to contribute to Predis. +open a new pull request with a description of the applied changes. Obviously, you +can use any other Git hosting provider of your preference. ## Dependencies ## -- PHP >= 5.3.0 +- PHP >= 5.3.2 - PHPUnit >= 3.5.0 (needed to run the test suite) ## Links ## diff --git a/TODO b/TODO index 97e7ce6a..3ea86486 100644 --- a/TODO +++ b/TODO @@ -2,13 +2,5 @@ * Implement smart and transparent support for redis-cluster. -* Switch to smaller test units and add more granular tests that try to cover - every single class. - * Documentation! The README is obviously not enought to show how to use Predis as it does not cover all of its features. - -* Missing tests for commands: - PUBLISH, SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, DEBUG, OBJECT, - CLIENT, CONFIG GET, CONFIG SET, CONFIG RESETSTAT, SLOWLOG, SCRIPT, PTTL, - PSETEX, PEXPIRE, PEXPIREAT, INCRBYFLOAT, HINCRBYFLOAT diff --git a/bin/generate-command-test.php b/bin/generate-command-test.php new file mode 100755 index 00000000..dca47c9c --- /dev/null +++ b/bin/generate-command-test.php @@ -0,0 +1,237 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Predis\Commands\ICommand; +use Predis\Commands\IPrefixable; + +class CommandTestCaseGenerator +{ + private $options; + + public function __construct(Array $options) + { + if (!isset($options['class'])) { + throw new RuntimeException("Missing 'class' option."); + } + $this->options = $options; + } + + public static function fromCommandLine() + { + $parameters = array( + 'c:' => 'class:', + 'r::' => 'realm::', + 'o::' => 'output::', + 'x::' => 'overwrite::' + ); + + $getops = getopt(implode(array_keys($parameters)), $parameters); + + $options = array( + 'overwrite' => false, + 'tests' => __DIR__.'/../tests', + ); + + foreach ($getops as $option => $value) { + switch ($option) { + case 'c': + case 'class': + $options['class'] = $value; + break; + + case 'r': + case 'realm': + $options['realm'] = $value; + break; + + case 'o': + case 'output': + $options['output'] = $value; + break; + + case 'x': + case 'overwrite': + $options['overwrite'] = true; + break; + } + } + + if (!isset($options['class'])) { + throw new RuntimeException("Missing 'class' option."); + } + + $options['fqn'] = "Predis\\Commands\\{$options['class']}"; + $options['path'] = "Predis/Commands/{$options['class']}.php"; + + $source = __DIR__.'/../lib/'.$options['path']; + if (!file_exists($source)) { + throw new RuntimeException("Cannot find class file for {$options['fqn']} in $source."); + } + + if (!isset($options['output'])) { + $options['output'] = sprintf("%s/%s", $options['tests'], str_replace('.php', 'Test.php', $options['path'])); + } + + return new self($options); + } + + protected function getTestRealm() + { + if (isset($this->options['realm'])) { + if (!$this->options['realm']) { + throw new RuntimeException('Invalid value for realm has been sepcified (empty).'); + } + return $this->options['realm']; + } + + $class = array_pop(explode('\\', $this->options['fqn'])); + list($realm,) = preg_split('/([[:upper:]][[:lower:]]+)/', $class, 2, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + return strtolower($realm); + } + + public function generate() + { + $reflection = new ReflectionClass($class = $this->options['fqn']); + + if (!$reflection->isInstantiable()) { + throw new RuntimeException("Class $class must be instantiable, abstract classes or interfaces are not allowed."); + } + if (!$reflection->implementsInterface('Predis\Commands\ICommand')) { + throw new RuntimeException("Class $class must implement the Predis\Commands\ICommand interface."); + } + + $instance = $reflection->newInstance(); + $buffer = $this->getTestCaseBuffer($instance); + + return $buffer; + } + + public function save() + { + $options = $this->options; + if (file_exists($options['output']) && !$options['overwrite']) { + throw new RuntimeException("File {$options['output']} already exist. Specify the --overwrite option to overwrite the existing file."); + } + file_put_contents($options['output'], $this->generate()); + } + + protected function getTestCaseBuffer(ICommand $instance) + { + $id = $instance->getId(); + $fqn = get_class($instance); + $class = array_pop(explode('\\', $fqn)) . "Test"; + $realm = $this->getTestRealm(); + + $buffer =<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-$realm + */ +class $class extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return '$fqn'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return '$id'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + \$this->markTestIncomplete('This test has not been implemented yet.'); + + \$arguments = array(/* add arguments */); + \$expected = array(/* add arguments */); + + \$command = \$this->getCommand(); + \$command->setArguments(\$arguments); + + \$this->assertSame(\$expected, \$command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + \$this->markTestIncomplete('This test has not been implemented yet.'); + + \$raw = null; + \$expected = null; + + \$command = \$this->getCommand(); + + \$this->assertSame(\$expected, \$command->parseResponse(\$raw)); + } + +PHP; + + if ($instance instanceof IPrefixable) { + $buffer .=<<markTestIncomplete('This test has not been implemented yet.'); + + \$arguments = array(/* add arguments */); + \$expected = array(/* add arguments */); + + \$command = \$this->getCommandWithArgumentsArray(\$arguments); + \$command->prefixKeys('prefix:'); + + \$this->assertSame(\$expected, \$command->getArguments()); + } + +PHP; + } + + return "$buffer}\n"; + } +} + +// ------------------------------------------------------------------------- // + +require __DIR__.'/../autoload.php'; + +$generator = CommandTestCaseGenerator::fromCommandLine(); +$generator->save(); diff --git a/examples/ServerSideScripting.php b/examples/ServerSideScripting.php index 5087d3c0..e87cde5f 100644 --- a/examples/ServerSideScripting.php +++ b/examples/ServerSideScripting.php @@ -20,7 +20,7 @@ use Predis\Commands\ScriptedCommand; class IncrementExistingKey extends ScriptedCommand { - protected function keysCount() + public function getKeysCount() { return 1; } diff --git a/lib/Predis/Autoloader.php b/lib/Predis/Autoloader.php index 6dc6be74..3d59e09b 100644 --- a/lib/Predis/Autoloader.php +++ b/lib/Predis/Autoloader.php @@ -52,11 +52,6 @@ class Autoloader $relativeClassName = substr($className, strlen($this->prefix)); $classNameParts = explode('\\', $relativeClassName); - $path = $this->baseDir . - DIRECTORY_SEPARATOR . - implode(DIRECTORY_SEPARATOR, $classNameParts) . - '.php'; - - require_once $path; + require_once $this->baseDir.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $classNameParts).'.php'; } } diff --git a/lib/Predis/Client.php b/lib/Predis/Client.php index e98d109e..06e27751 100644 --- a/lib/Predis/Client.php +++ b/lib/Predis/Client.php @@ -191,11 +191,9 @@ class Client { if (isset($id)) { if (!Helpers::isCluster($this->connection)) { - throw new ClientException( - 'Retrieving connections by alias is supported only with clustered connections' - ); + $message = 'Retrieving connections by alias is supported only with clustered connections'; + throw new NotSupportedException($message); } - return $this->connection->getConnectionById($id); } diff --git a/lib/Predis/Commands/HashDelete.php b/lib/Predis/Commands/HashDelete.php index fbdf35a7..aa9724af 100644 --- a/lib/Predis/Commands/HashDelete.php +++ b/lib/Predis/Commands/HashDelete.php @@ -34,12 +34,4 @@ class HashDelete extends PrefixableCommand { return Helpers::filterVariadicValues($arguments); } - - /** - * {@inheritdoc} - */ - public function parseResponse($data) - { - return (bool) $data; - } } diff --git a/lib/Predis/Commands/KeyKeysV12x.php b/lib/Predis/Commands/KeyKeysV12x.php index 262cc3b5..1eccae93 100644 --- a/lib/Predis/Commands/KeyKeysV12x.php +++ b/lib/Predis/Commands/KeyKeysV12x.php @@ -14,6 +14,7 @@ namespace Predis\Commands; /** * @link http://redis.io/commands/keys * @author Daniele Alessandri + * @deprecated */ class KeyKeysV12x extends KeyKeys { diff --git a/lib/Predis/Commands/KeyRandom.php b/lib/Predis/Commands/KeyRandom.php index 0102a75b..51c34f61 100644 --- a/lib/Predis/Commands/KeyRandom.php +++ b/lib/Predis/Commands/KeyRandom.php @@ -15,7 +15,7 @@ namespace Predis\Commands; * @link http://redis.io/commands/randomkey * @author Daniele Alessandri */ -class KeyRandom extends PrefixableCommand +class KeyRandom extends Command { /** * {@inheritdoc} diff --git a/lib/Predis/Commands/ListPopFirstBlocking.php b/lib/Predis/Commands/ListPopFirstBlocking.php index bf5db0d3..5a348be9 100644 --- a/lib/Predis/Commands/ListPopFirstBlocking.php +++ b/lib/Predis/Commands/ListPopFirstBlocking.php @@ -25,6 +25,18 @@ class ListPopFirstBlocking extends Command implements IPrefixable return 'BLPOP'; } + /** + * {@inheritdoc} + */ + protected function filterArguments(Array $arguments) + { + if (count($arguments) === 2 && is_array($arguments[0])) { + list($arguments, $timeout) = $arguments; + array_push($arguments, $timeout); + } + return $arguments; + } + /** * {@inheritdoc} */ diff --git a/lib/Predis/Commands/PrefixHelpers.php b/lib/Predis/Commands/PrefixHelpers.php index e69d75e4..f344eed5 100644 --- a/lib/Predis/Commands/PrefixHelpers.php +++ b/lib/Predis/Commands/PrefixHelpers.php @@ -24,12 +24,12 @@ class PrefixHelpers * @param ICommand $command Command instance. * @param string $prefix Prefix string. */ - public function first(ICommand $command, $prefix) { - $arguments = $command->getArguments(); - - $arguments[0] = "$prefix{$arguments[0]}"; - - $command->setRawArguments($arguments); + public function first(ICommand $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $arguments[0] = "$prefix{$arguments[0]}"; + $command->setRawArguments($arguments); + } } /** diff --git a/lib/Predis/Commands/PrefixableCommand.php b/lib/Predis/Commands/PrefixableCommand.php index 2d8347f6..21289d88 100644 --- a/lib/Predis/Commands/PrefixableCommand.php +++ b/lib/Predis/Commands/PrefixableCommand.php @@ -23,8 +23,9 @@ abstract class PrefixableCommand extends Command implements IPrefixable */ public function prefixKeys($prefix) { - $arguments = $this->getArguments(); - $arguments[0] = "$prefix{$arguments[0]}"; - $this->setRawArguments($arguments); + if ($arguments = $this->getArguments()) { + $arguments[0] = "$prefix{$arguments[0]}"; + $this->setRawArguments($arguments); + } } } diff --git a/lib/Predis/Commands/Processors/ProcessorChain.php b/lib/Predis/Commands/Processors/ProcessorChain.php index 6018000f..867cc6b3 100644 --- a/lib/Predis/Commands/Processors/ProcessorChain.php +++ b/lib/Predis/Commands/Processors/ProcessorChain.php @@ -20,7 +20,7 @@ use Predis\Commands\ICommand; */ class ProcessorChain implements ICommandProcessorChain, \ArrayAccess { - private $processors; + private $processors = array(); /** * @param array $processors List of instances of ICommandProcessor. @@ -127,5 +127,6 @@ class ProcessorChain implements ICommandProcessorChain, \ArrayAccess public function offsetUnset($index) { unset($this->processors[$index]); + $this->processors = array_values($this->processors); } } diff --git a/lib/Predis/Commands/PubSubUnsubscribe.php b/lib/Predis/Commands/PubSubUnsubscribe.php index 0f65ecb0..e17c553c 100644 --- a/lib/Predis/Commands/PubSubUnsubscribe.php +++ b/lib/Predis/Commands/PubSubUnsubscribe.php @@ -11,6 +11,8 @@ namespace Predis\Commands; +use Predis\Helpers; + /** * @link http://redis.io/commands/unsubscribe * @author Daniele Alessandri @@ -25,6 +27,14 @@ class PubSubUnsubscribe extends Command implements IPrefixable return 'UNSUBSCRIBE'; } + /** + * {@inheritdoc} + */ + protected function filterArguments(Array $arguments) + { + return Helpers::filterArrayArguments($arguments); + } + /** * {@inheritdoc} */ diff --git a/lib/Predis/Commands/ScriptedCommand.php b/lib/Predis/Commands/ScriptedCommand.php index 769457a1..c3319638 100644 --- a/lib/Predis/Commands/ScriptedCommand.php +++ b/lib/Predis/Commands/ScriptedCommand.php @@ -27,12 +27,16 @@ abstract class ScriptedCommand extends ServerEval */ public abstract function getScript(); - /* + /** * Gets the number of arguments that should be considered as keys. * + * @todo Should we make a scripted command act by default as a variadic + * command where the first argument is the key (KEYS[1]) and the + * rest is the list of values (ARGV)? + * * @return int */ - protected function keysCount() + public function getKeysCount() { // The default behaviour for the base class is to use all the arguments // passed to a scripted command to populate the KEYS table in Lua. @@ -40,18 +44,20 @@ abstract class ScriptedCommand extends ServerEval } /** - * {@inheritdoc} + * Returns the elements from the arguments that are identified as keys. + * + * @return array */ - protected function filterArguments(Array $arguments) + public function getKeys() { - return array_merge(array($this->getScript(), $this->keysCount()), $arguments); + return array_slice($this->getArguments(), 2, $this->getKeysCount()); } /** * {@inheritdoc} */ - protected function getKeys() + protected function filterArguments(Array $arguments) { - return array_slice($this->getArguments(), 2, $this->keysCount()); + return array_merge(array($this->getScript(), $this->getKeysCount()), $arguments); } } diff --git a/lib/Predis/Commands/ServerEval.php b/lib/Predis/Commands/ServerEval.php index 0095686d..4b3ed4f3 100644 --- a/lib/Predis/Commands/ServerEval.php +++ b/lib/Predis/Commands/ServerEval.php @@ -36,7 +36,7 @@ class ServerEval extends Command implements IPrefixable $arguments[$i] = "$prefix{$arguments[$i]}"; } - return $arguments; + $this->setRawArguments($arguments); } /** diff --git a/lib/Predis/Commands/ServerInfo.php b/lib/Predis/Commands/ServerInfo.php index 347c1aec..a4edc20f 100644 --- a/lib/Predis/Commands/ServerInfo.php +++ b/lib/Predis/Commands/ServerInfo.php @@ -39,7 +39,7 @@ class ServerInfo extends Command public function parseResponse($data) { $info = array(); - $infoLines = explode("\r\n", $data, -1); + $infoLines = preg_split('/\r?\n/', $data); foreach ($infoLines as $row) { @list($k, $v) = explode(':', $row); diff --git a/lib/Predis/Commands/ServerInfoV26x.php b/lib/Predis/Commands/ServerInfoV26x.php index cc58c0ee..d6fb619a 100644 --- a/lib/Predis/Commands/ServerInfoV26x.php +++ b/lib/Predis/Commands/ServerInfoV26x.php @@ -24,7 +24,11 @@ class ServerInfoV26x extends ServerInfo { $info = array(); $current = null; - $infoLines = explode("\r\n", $data, -1); + $infoLines = preg_split('/\r?\n/', $data); + + if (isset($infoLines[0]) && $infoLines[0][0] !== '#') { + return parent::parseResponse($data); + } foreach ($infoLines as $row) { if ($row === '') { diff --git a/lib/Predis/Commands/SetAdd.php b/lib/Predis/Commands/SetAdd.php index 112cbb96..6738e04a 100644 --- a/lib/Predis/Commands/SetAdd.php +++ b/lib/Predis/Commands/SetAdd.php @@ -34,12 +34,4 @@ class SetAdd extends PrefixableCommand { return Helpers::filterVariadicValues($arguments); } - - /** - * {@inheritdoc} - */ - public function parseResponse($data) - { - return (bool) $data; - } } diff --git a/lib/Predis/Commands/SetRemove.php b/lib/Predis/Commands/SetRemove.php index 78aa3020..2e9ba3a9 100644 --- a/lib/Predis/Commands/SetRemove.php +++ b/lib/Predis/Commands/SetRemove.php @@ -34,12 +34,4 @@ class SetRemove extends PrefixableCommand { return Helpers::filterVariadicValues($arguments); } - - /** - * {@inheritdoc} - */ - public function parseResponse($data) - { - return (bool) $data; - } } diff --git a/lib/Predis/Commands/ZSetAdd.php b/lib/Predis/Commands/ZSetAdd.php index 2df5b31c..e369bc58 100644 --- a/lib/Predis/Commands/ZSetAdd.php +++ b/lib/Predis/Commands/ZSetAdd.php @@ -32,14 +32,16 @@ class ZSetAdd extends PrefixableCommand */ protected function filterArguments(Array $arguments) { - return Helpers::filterVariadicValues($arguments); - } + if (count($arguments) === 2 && is_array($arguments[1])) { + $flattened = array($arguments[0]); + foreach($arguments[1] as $member => $score) { + $flattened[] = $score; + $flattened[] = $member; + } - /** - * {@inheritdoc} - */ - public function parseResponse($data) - { - return (bool) $data; + return $flattened; + } + + return $arguments; } } diff --git a/lib/Predis/Commands/ZSetRemove.php b/lib/Predis/Commands/ZSetRemove.php index 6d7ee626..2ebb71bd 100644 --- a/lib/Predis/Commands/ZSetRemove.php +++ b/lib/Predis/Commands/ZSetRemove.php @@ -34,12 +34,4 @@ class ZSetRemove extends PrefixableCommand { return Helpers::filterVariadicValues($arguments); } - - /** - * {@inheritdoc} - */ - public function parseResponse($data) - { - return (bool) $data; - } } diff --git a/lib/Predis/Iterators/MultiBulkResponseSimple.php b/lib/Predis/Iterators/MultiBulkResponseSimple.php index 943c8e44..4f37307c 100644 --- a/lib/Predis/Iterators/MultiBulkResponseSimple.php +++ b/lib/Predis/Iterators/MultiBulkResponseSimple.php @@ -42,7 +42,7 @@ class MultiBulkResponseSimple extends MultiBulkResponse */ public function __destruct() { - $this->sync(); + $this->sync(true); } /** diff --git a/lib/Predis/Iterators/MultiBulkResponseTuple.php b/lib/Predis/Iterators/MultiBulkResponseTuple.php index a84fdba1..163669e9 100644 --- a/lib/Predis/Iterators/MultiBulkResponseTuple.php +++ b/lib/Predis/Iterators/MultiBulkResponseTuple.php @@ -17,7 +17,7 @@ namespace Predis\Iterators; * * @author Daniele Alessandri */ -class MultiBulkResponseTuple extends MultiBulkResponse +class MultiBulkResponseTuple extends MultiBulkResponse implements \OuterIterator { private $iterator; @@ -33,12 +33,20 @@ class MultiBulkResponseTuple extends MultiBulkResponse $this->replySize = $virtualSize; } + /** + * {@inheritdoc} + */ + public function getInnerIterator() + { + return $this->iterator; + } + /** * {@inheritdoc} */ public function __destruct() { - $this->iterator->sync(); + $this->iterator->sync(true); } /** diff --git a/lib/Predis/MonitorContext.php b/lib/Predis/MonitorContext.php index eb3fdc91..82af112e 100644 --- a/lib/Predis/MonitorContext.php +++ b/lib/Predis/MonitorContext.php @@ -49,15 +49,11 @@ class MonitorContext implements \Iterator private function checkCapabilities(Client $client) { if (Helpers::isCluster($client->getConnection())) { - throw new ClientException( - 'Cannot initialize a monitor context over a cluster of connections' - ); + throw new NotSupportedException('Cannot initialize a monitor context over a cluster of connections'); } if ($client->getProfile()->supportsCommand('monitor') === false) { - throw new ClientException( - 'The current profile does not support the MONITOR command' - ); + throw new NotSupportedException('The current profile does not support the MONITOR command'); } } diff --git a/lib/Predis/Network/ConnectionBase.php b/lib/Predis/Network/ConnectionBase.php index a175793d..70d40e96 100644 --- a/lib/Predis/Network/ConnectionBase.php +++ b/lib/Predis/Network/ConnectionBase.php @@ -11,7 +11,6 @@ namespace Predis\Network; -use \InvalidArgumentException; use Predis\Helpers; use Predis\IReplyObject; use Predis\IConnectionParameters; @@ -61,14 +60,14 @@ abstract class ConnectionBase implements IConnectionSingle switch ($parameters->scheme) { case 'unix': if (!isset($parameters->path)) { - throw new InvalidArgumentException('Missing UNIX domain socket path'); + throw new \InvalidArgumentException('Missing UNIX domain socket path'); } case 'tcp': return $parameters; default: - throw new InvalidArgumentException("Invalid scheme: {$parameters->scheme}"); + throw new \InvalidArgumentException("Invalid scheme: {$parameters->scheme}"); } } @@ -182,7 +181,7 @@ abstract class ConnectionBase implements IConnectionSingle $message .= " [$parameters]"; } - throw new InvalidArgumentException($message); + throw new \InvalidArgumentException($message); } /** diff --git a/lib/Predis/Network/PhpiredisConnection.php b/lib/Predis/Network/PhpiredisConnection.php index 75982271..990386d5 100644 --- a/lib/Predis/Network/PhpiredisConnection.php +++ b/lib/Predis/Network/PhpiredisConnection.php @@ -11,12 +11,13 @@ namespace Predis\Network; +use Predis\Commands\ICommand; +use Predis\IConnectionParameters; use Predis\ResponseError; use Predis\ResponseQueued; use Predis\ClientException; use Predis\ServerException; -use Predis\IConnectionParameters; -use Predis\Commands\ICommand; +use Predis\NotSupportedException; /** * This class provides the implementation of a Predis connection that uses the @@ -47,7 +48,7 @@ class PhpiredisConnection extends ConnectionBase public function __construct(IConnectionParameters $parameters) { if (!function_exists('socket_create')) { - throw new ClientException( + throw new NotSupportedException( 'The socket extension must be loaded in order to be able to ' . 'use this connection class' ); @@ -90,7 +91,7 @@ class PhpiredisConnection extends ConnectionBase private function initializeReader($throw_errors = true) { if (!function_exists('phpiredis_reader_create')) { - throw new ClientException( + throw new NotSupportedException( 'The phpiredis extension must be loaded in order to be able to ' . 'use this connection class' ); diff --git a/lib/Predis/Network/PredisCluster.php b/lib/Predis/Network/PredisCluster.php index 14e250fd..b8c517a4 100644 --- a/lib/Predis/Network/PredisCluster.php +++ b/lib/Predis/Network/PredisCluster.php @@ -11,10 +11,11 @@ namespace Predis\Network; -use Predis\Helpers; -use Predis\ClientException; use Predis\Commands\ICommand; use Predis\Distribution\IDistributionStrategy; +use Predis\Helpers; +use Predis\ClientException; +use Predis\NotSupportedException; use Predis\Distribution\HashRing; /** @@ -22,6 +23,7 @@ use Predis\Distribution\HashRing; * implementing client-side sharding based on pluggable distribution strategies. * * @author Daniele Alessandri + * @todo Add the ability to remove connections from pool. */ class PredisCluster implements IConnectionCluster, \IteratorAggregate { @@ -85,7 +87,8 @@ class PredisCluster implements IConnectionCluster, \IteratorAggregate $this->pool[] = $connection; } - $this->distributor->add($connection, $parameters->weight); + $weight = isset($parameters->weight) ? $parameters->weight : null; + $this->distributor->add($connection, $weight); } /** @@ -99,9 +102,8 @@ class PredisCluster implements IConnectionCluster, \IteratorAggregate return $this->distributor->get($cmdHash); } - throw new ClientException( - sprintf("Cannot send '%s' commands to a cluster of connections", $command->getId()) - ); + $message = sprintf("Cannot send '%s' commands to a cluster of connections", $command->getId()); + throw new NotSupportedException($message); } /** diff --git a/lib/Predis/Network/StreamConnection.php b/lib/Predis/Network/StreamConnection.php index 8e803688..7c207691 100644 --- a/lib/Predis/Network/StreamConnection.php +++ b/lib/Predis/Network/StreamConnection.php @@ -14,6 +14,7 @@ namespace Predis\Network; use Predis\ResponseError; use Predis\ResponseQueued; use Predis\ServerException; +use Predis\NotSupportedException; use Predis\IConnectionParameters; use Predis\Commands\ICommand; use Predis\Iterators\MultiBulkResponseSimple; diff --git a/lib/Predis/Network/WebdisConnection.php b/lib/Predis/Network/WebdisConnection.php index ec071850..bdac4c72 100644 --- a/lib/Predis/Network/WebdisConnection.php +++ b/lib/Predis/Network/WebdisConnection.php @@ -11,12 +11,13 @@ namespace Predis\Network; +use Predis\Commands\ICommand; use Predis\IConnectionParameters; use Predis\ResponseError; -use Predis\ClientException; use Predis\ServerException; -use Predis\Commands\ICommand; +use Predis\NotSupportedException; use Predis\Protocol\ProtocolException; +use Predis\Network\ConnectionException; const ERR_MSG_EXTENSION = 'The %s extension must be loaded in order to be able to use this connection class'; @@ -74,7 +75,7 @@ class WebdisConnection implements IConnectionSingle private function throwNotSupportedException($function) { $class = __CLASS__; - throw new \RuntimeException("The method $class::$function() is not supported"); + throw new NotSupportedException("The method $class::$function() is not supported"); } /** @@ -83,10 +84,10 @@ class WebdisConnection implements IConnectionSingle private function checkExtensions() { if (!function_exists('curl_init')) { - throw new ClientException(sprintf(ERR_MSG_EXTENSION, 'curl')); + throw new NotSupportedException(sprintf(ERR_MSG_EXTENSION, 'curl')); } if (!function_exists('phpiredis_reader_create')) { - throw new ClientException(sprintf(ERR_MSG_EXTENSION, 'phpiredis')); + throw new NotSupportedException(sprintf(ERR_MSG_EXTENSION, 'phpiredis')); } } @@ -138,7 +139,7 @@ class WebdisConnection implements IConnectionSingle * * @return \Closure */ - private function getStatusHandler() + protected function getStatusHandler() { return function($payload) { return $payload === 'OK' ? true : $payload; @@ -151,7 +152,7 @@ class WebdisConnection implements IConnectionSingle * @param Boolean $throwErrors Specify if Redis errors throw exceptions. * @return \Closure */ - private function getErrorHandler($throwErrors) + protected function getErrorHandler($throwErrors) { if ($throwErrors) { return function($errorMessage) { @@ -218,7 +219,8 @@ class WebdisConnection implements IConnectionSingle case 'WATCH': case 'UNWATCH': case 'DISCARD': - throw new \InvalidArgumentException("Disabled command: {$command->getId()}"); + case 'MONITOR': + throw new NotSupportedException("Disabled command: {$command->getId()}"); default: return $commandId; diff --git a/lib/Predis/NotSupportedException.php b/lib/Predis/NotSupportedException.php new file mode 100644 index 00000000..631b820a --- /dev/null +++ b/lib/Predis/NotSupportedException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +/** + * Exception class generated when trying to use features not + * supported by certain classes or abstractions. + * + * @author Daniele Alessandri + */ +class NotSupportedException extends PredisException +{ +} diff --git a/lib/Predis/Options/ClientCluster.php b/lib/Predis/Options/ClientCluster.php index 6f8ee530..920a04e0 100644 --- a/lib/Predis/Options/ClientCluster.php +++ b/lib/Predis/Options/ClientCluster.php @@ -30,9 +30,7 @@ class ClientCluster extends Option protected function checkInstance($cluster) { if (!$cluster instanceof IConnectionCluster) { - throw new \InvalidArgumentException( - 'Instance of Predis\Network\IConnectionCluster expected' - ); + throw new \InvalidArgumentException('Instance of Predis\Network\IConnectionCluster expected'); } return $cluster; @@ -44,7 +42,7 @@ class ClientCluster extends Option public function validate(IClientOptions $options, $value) { if (is_callable($value)) { - return $this->checkInstance(call_user_func($value)); + return $this->checkInstance(call_user_func($value, $options)); } $initializer = $this->getInitializer($options, $value); @@ -54,7 +52,7 @@ class ClientCluster extends Option /** * Returns an initializer for the specified FQN or type. * - * @param string $fqnOrType Type of cluster of FQN of a class implementing IConnectionCluster. + * @param string $fqnOrType Type of cluster or FQN of a class implementing IConnectionCluster. * @param IClientOptions $options Instance of the client options. * @return \Closure */ @@ -65,6 +63,10 @@ class ClientCluster extends Option return function() { return new PredisCluster(); }; 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(); }; diff --git a/lib/Predis/Options/ClientConnectionFactory.php b/lib/Predis/Options/ClientConnectionFactory.php index 934bb56b..21f396da 100644 --- a/lib/Predis/Options/ClientConnectionFactory.php +++ b/lib/Predis/Options/ClientConnectionFactory.php @@ -36,6 +36,14 @@ class ClientConnectionFactory extends Option } return $factory; } + if (is_string($value) && class_exists($value)) { + if (!($factory = new $value()) && !$factory instanceof IConnectionFactory) { + throw new \InvalidArgumentException("Class $value must be an instance of Predis\IConnectionFactory"); + } + return $factory; + } + + throw new \InvalidArgumentException('Invalid value for the connections option'); } /** diff --git a/lib/Predis/Options/CustomOption.php b/lib/Predis/Options/CustomOption.php index 5a8e2fe9..7775d401 100644 --- a/lib/Predis/Options/CustomOption.php +++ b/lib/Predis/Options/CustomOption.php @@ -24,7 +24,7 @@ class CustomOption implements IOption /** * @param array $options List of options */ - public function __construct(Array $options) + public function __construct(Array $options = array()) { $this->validate = $this->filterCallable($options, 'validate'); $this->default = $this->filterCallable($options, 'default'); diff --git a/lib/Predis/Pipeline/PipelineContext.php b/lib/Predis/Pipeline/PipelineContext.php index 6151ce64..bc5c91b4 100644 --- a/lib/Predis/Pipeline/PipelineContext.php +++ b/lib/Predis/Pipeline/PipelineContext.php @@ -38,7 +38,7 @@ class PipelineContext public function __construct(Client $client, Array $options = null) { $this->client = $client; - $this->executor = $this->getExecutor($client, $options ?: array()); + $this->executor = $this->createExecutor($client, $options ?: array()); } /** @@ -49,7 +49,7 @@ class PipelineContext * @param array Options for the context initialization. * @return IPipelineExecutor */ - protected function getExecutor(Client $client, Array $options) + protected function createExecutor(Client $client, Array $options) { if (!$options) { return new StandardExecutor(); @@ -160,7 +160,7 @@ class PipelineContext try { if ($callable !== null) { - $callable($this); + call_user_func($callable, $this); } $this->flushPipeline(); } @@ -186,4 +186,14 @@ class PipelineContext { return $this->client; } + + /** + * Returns the underlying pipeline executor used by the pipeline object. + * + * @return IPipelineExecutor + */ + public function getExecutor() + { + return $this->executor; + } } diff --git a/lib/Predis/Profiles/ServerProfile.php b/lib/Predis/Profiles/ServerProfile.php index a4f43564..eb73abd5 100644 --- a/lib/Predis/Profiles/ServerProfile.php +++ b/lib/Predis/Profiles/ServerProfile.php @@ -96,9 +96,7 @@ abstract class ServerProfile implements IServerProfile, IProcessingSupport $profileReflection = new \ReflectionClass($profileClass); if (!$profileReflection->isSubclassOf('Predis\Profiles\IServerProfile')) { - throw new ClientException( - "Cannot register '$profileClass' as it is not a valid profile class" - ); + throw new \InvalidArgumentException("Cannot register '$profileClass' as it is not a valid profile class"); } self::$profiles[$alias] = $profileClass; @@ -146,6 +144,20 @@ abstract class ServerProfile implements IServerProfile, IProcessingSupport return isset($this->commands[strtolower($command)]); } + /** + * Returns the FQN of the class that represent the specified command ID + * registered in the current server profile. + * + * @param string $command Command ID. + * @return string + */ + public function getCommandClass($command) + { + if (isset($this->commands[$command = strtolower($command)])) { + return $this->commands[$command]; + } + } + /** * {@inheritdoc} */ @@ -189,7 +201,7 @@ abstract class ServerProfile implements IServerProfile, IProcessingSupport { $commandReflection = new \ReflectionClass($command); if (!$commandReflection->isSubclassOf('Predis\Commands\ICommand')) { - throw new ClientException("Cannot register '$command' as it is not a valid Redis command"); + throw new \InvalidArgumentException("Cannot register '$command' as it is not a valid Redis command"); } $this->commands[strtolower($alias)] = $command; } @@ -197,12 +209,8 @@ abstract class ServerProfile implements IServerProfile, IProcessingSupport /** * {@inheritdoc} */ - public function setProcessor(ICommandProcessor $processor) + public function setProcessor(ICommandProcessor $processor = null) { - if (!isset($processor)) { - unset($this->processor); - return; - } $this->processor = $processor; } diff --git a/lib/Predis/Profiles/ServerVersion12.php b/lib/Predis/Profiles/ServerVersion12.php index d89caebb..3aa94f25 100644 --- a/lib/Predis/Profiles/ServerVersion12.php +++ b/lib/Predis/Profiles/ServerVersion12.php @@ -35,91 +35,91 @@ class ServerVersion12 extends ServerProfile /* ---------------- Redis 1.2 ---------------- */ /* commands operating on the key space */ - 'exists' => '\Predis\Commands\KeyExists', - 'del' => '\Predis\Commands\KeyDelete', - 'type' => '\Predis\Commands\KeyType', - 'keys' => '\Predis\Commands\KeyKeysV12x', - 'randomkey' => '\Predis\Commands\KeyRandom', - 'rename' => '\Predis\Commands\KeyRename', - 'renamenx' => '\Predis\Commands\KeyRenamePreserve', - 'expire' => '\Predis\Commands\KeyExpire', - 'expireat' => '\Predis\Commands\KeyExpireAt', - 'ttl' => '\Predis\Commands\KeyTimeToLive', - 'move' => '\Predis\Commands\KeyMove', - 'sort' => '\Predis\Commands\KeySort', + 'exists' => 'Predis\Commands\KeyExists', + 'del' => 'Predis\Commands\KeyDelete', + 'type' => 'Predis\Commands\KeyType', + 'keys' => 'Predis\Commands\KeyKeysV12x', + 'randomkey' => 'Predis\Commands\KeyRandom', + 'rename' => 'Predis\Commands\KeyRename', + 'renamenx' => 'Predis\Commands\KeyRenamePreserve', + 'expire' => 'Predis\Commands\KeyExpire', + 'expireat' => 'Predis\Commands\KeyExpireAt', + 'ttl' => 'Predis\Commands\KeyTimeToLive', + 'move' => 'Predis\Commands\KeyMove', + 'sort' => 'Predis\Commands\KeySort', /* commands operating on string values */ - 'set' => '\Predis\Commands\StringSet', - 'setnx' => '\Predis\Commands\StringSetPreserve', - 'mset' => '\Predis\Commands\StringSetMultiple', - 'msetnx' => '\Predis\Commands\StringSetMultiplePreserve', - 'get' => '\Predis\Commands\StringGet', - 'mget' => '\Predis\Commands\StringGetMultiple', - 'getset' => '\Predis\Commands\StringGetSet', - 'incr' => '\Predis\Commands\StringIncrement', - 'incrby' => '\Predis\Commands\StringIncrementBy', - 'decr' => '\Predis\Commands\StringDecrement', - 'decrby' => '\Predis\Commands\StringDecrementBy', + 'set' => 'Predis\Commands\StringSet', + 'setnx' => 'Predis\Commands\StringSetPreserve', + 'mset' => 'Predis\Commands\StringSetMultiple', + 'msetnx' => 'Predis\Commands\StringSetMultiplePreserve', + 'get' => 'Predis\Commands\StringGet', + 'mget' => 'Predis\Commands\StringGetMultiple', + 'getset' => 'Predis\Commands\StringGetSet', + 'incr' => 'Predis\Commands\StringIncrement', + 'incrby' => 'Predis\Commands\StringIncrementBy', + 'decr' => 'Predis\Commands\StringDecrement', + 'decrby' => 'Predis\Commands\StringDecrementBy', /* commands operating on lists */ - 'rpush' => '\Predis\Commands\ListPushTail', - 'lpush' => '\Predis\Commands\ListPushHead', - 'llen' => '\Predis\Commands\ListLength', - 'lrange' => '\Predis\Commands\ListRange', - 'ltrim' => '\Predis\Commands\ListTrim', - 'lindex' => '\Predis\Commands\ListIndex', - 'lset' => '\Predis\Commands\ListSet', - 'lrem' => '\Predis\Commands\ListRemove', - 'lpop' => '\Predis\Commands\ListPopFirst', - 'rpop' => '\Predis\Commands\ListPopLast', - 'rpoplpush' => '\Predis\Commands\ListPopLastPushHead', + 'rpush' => 'Predis\Commands\ListPushTail', + 'lpush' => 'Predis\Commands\ListPushHead', + 'llen' => 'Predis\Commands\ListLength', + 'lrange' => 'Predis\Commands\ListRange', + 'ltrim' => 'Predis\Commands\ListTrim', + 'lindex' => 'Predis\Commands\ListIndex', + 'lset' => 'Predis\Commands\ListSet', + 'lrem' => 'Predis\Commands\ListRemove', + 'lpop' => 'Predis\Commands\ListPopFirst', + 'rpop' => 'Predis\Commands\ListPopLast', + 'rpoplpush' => 'Predis\Commands\ListPopLastPushHead', /* commands operating on sets */ - 'sadd' => '\Predis\Commands\SetAdd', - 'srem' => '\Predis\Commands\SetRemove', - 'spop' => '\Predis\Commands\SetPop', - 'smove' => '\Predis\Commands\SetMove', - 'scard' => '\Predis\Commands\SetCardinality', - 'sismember' => '\Predis\Commands\SetIsMember', - 'sinter' => '\Predis\Commands\SetIntersection', - 'sinterstore' => '\Predis\Commands\SetIntersectionStore', - 'sunion' => '\Predis\Commands\SetUnion', - 'sunionstore' => '\Predis\Commands\SetUnionStore', - 'sdiff' => '\Predis\Commands\SetDifference', - 'sdiffstore' => '\Predis\Commands\SetDifferenceStore', - 'smembers' => '\Predis\Commands\SetMembers', - 'srandmember' => '\Predis\Commands\SetRandomMember', + 'sadd' => 'Predis\Commands\SetAdd', + 'srem' => 'Predis\Commands\SetRemove', + 'spop' => 'Predis\Commands\SetPop', + 'smove' => 'Predis\Commands\SetMove', + 'scard' => 'Predis\Commands\SetCardinality', + 'sismember' => 'Predis\Commands\SetIsMember', + 'sinter' => 'Predis\Commands\SetIntersection', + 'sinterstore' => 'Predis\Commands\SetIntersectionStore', + 'sunion' => 'Predis\Commands\SetUnion', + 'sunionstore' => 'Predis\Commands\SetUnionStore', + 'sdiff' => 'Predis\Commands\SetDifference', + 'sdiffstore' => 'Predis\Commands\SetDifferenceStore', + 'smembers' => 'Predis\Commands\SetMembers', + 'srandmember' => 'Predis\Commands\SetRandomMember', /* commands operating on sorted sets */ - 'zadd' => '\Predis\Commands\ZSetAdd', - 'zincrby' => '\Predis\Commands\ZSetIncrementBy', - 'zrem' => '\Predis\Commands\ZSetRemove', - 'zrange' => '\Predis\Commands\ZSetRange', - 'zrevrange' => '\Predis\Commands\ZSetReverseRange', - 'zrangebyscore' => '\Predis\Commands\ZSetRangeByScore', - 'zcard' => '\Predis\Commands\ZSetCardinality', - 'zscore' => '\Predis\Commands\ZSetScore', - 'zremrangebyscore' => '\Predis\Commands\ZSetRemoveRangeByScore', + 'zadd' => 'Predis\Commands\ZSetAdd', + 'zincrby' => 'Predis\Commands\ZSetIncrementBy', + 'zrem' => 'Predis\Commands\ZSetRemove', + 'zrange' => 'Predis\Commands\ZSetRange', + 'zrevrange' => 'Predis\Commands\ZSetReverseRange', + 'zrangebyscore' => 'Predis\Commands\ZSetRangeByScore', + 'zcard' => 'Predis\Commands\ZSetCardinality', + 'zscore' => 'Predis\Commands\ZSetScore', + 'zremrangebyscore' => 'Predis\Commands\ZSetRemoveRangeByScore', /* connection related commands */ - 'ping' => '\Predis\Commands\ConnectionPing', - 'auth' => '\Predis\Commands\ConnectionAuth', - 'select' => '\Predis\Commands\ConnectionSelect', - 'echo' => '\Predis\Commands\ConnectionEcho', - 'quit' => '\Predis\Commands\ConnectionQuit', + 'ping' => 'Predis\Commands\ConnectionPing', + 'auth' => 'Predis\Commands\ConnectionAuth', + 'select' => 'Predis\Commands\ConnectionSelect', + 'echo' => 'Predis\Commands\ConnectionEcho', + 'quit' => 'Predis\Commands\ConnectionQuit', /* remote server control commands */ - 'info' => '\Predis\Commands\ServerInfo', - 'slaveof' => '\Predis\Commands\ServerSlaveOf', - 'monitor' => '\Predis\Commands\ServerMonitor', - 'dbsize' => '\Predis\Commands\ServerDatabaseSize', - 'flushdb' => '\Predis\Commands\ServerFlushDatabase', - 'flushall' => '\Predis\Commands\ServerFlushAll', - 'save' => '\Predis\Commands\ServerSave', - 'bgsave' => '\Predis\Commands\ServerBackgroundSave', - 'lastsave' => '\Predis\Commands\ServerLastSave', - 'shutdown' => '\Predis\Commands\ServerShutdown', - 'bgrewriteaof' => '\Predis\Commands\ServerBackgroundRewriteAOF', + 'info' => 'Predis\Commands\ServerInfo', + 'slaveof' => 'Predis\Commands\ServerSlaveOf', + 'monitor' => 'Predis\Commands\ServerMonitor', + 'dbsize' => 'Predis\Commands\ServerDatabaseSize', + 'flushdb' => 'Predis\Commands\ServerFlushDatabase', + 'flushall' => 'Predis\Commands\ServerFlushAll', + 'save' => 'Predis\Commands\ServerSave', + 'bgsave' => 'Predis\Commands\ServerBackgroundSave', + 'lastsave' => 'Predis\Commands\ServerLastSave', + 'shutdown' => 'Predis\Commands\ServerShutdown', + 'bgrewriteaof' => 'Predis\Commands\ServerBackgroundRewriteAOF', ); } } diff --git a/lib/Predis/Profiles/ServerVersion20.php b/lib/Predis/Profiles/ServerVersion20.php index 8c64a597..002254a1 100644 --- a/lib/Predis/Profiles/ServerVersion20.php +++ b/lib/Predis/Profiles/ServerVersion20.php @@ -35,140 +35,140 @@ class ServerVersion20 extends ServerProfile /* ---------------- Redis 1.2 ---------------- */ /* commands operating on the key space */ - 'exists' => '\Predis\Commands\KeyExists', - 'del' => '\Predis\Commands\KeyDelete', - 'type' => '\Predis\Commands\KeyType', - 'keys' => '\Predis\Commands\KeyKeys', - 'randomkey' => '\Predis\Commands\KeyRandom', - 'rename' => '\Predis\Commands\KeyRename', - 'renamenx' => '\Predis\Commands\KeyRenamePreserve', - 'expire' => '\Predis\Commands\KeyExpire', - 'expireat' => '\Predis\Commands\KeyExpireAt', - 'ttl' => '\Predis\Commands\KeyTimeToLive', - 'move' => '\Predis\Commands\KeyMove', - 'sort' => '\Predis\Commands\KeySort', + 'exists' => 'Predis\Commands\KeyExists', + 'del' => 'Predis\Commands\KeyDelete', + 'type' => 'Predis\Commands\KeyType', + 'keys' => 'Predis\Commands\KeyKeys', + 'randomkey' => 'Predis\Commands\KeyRandom', + 'rename' => 'Predis\Commands\KeyRename', + 'renamenx' => 'Predis\Commands\KeyRenamePreserve', + 'expire' => 'Predis\Commands\KeyExpire', + 'expireat' => 'Predis\Commands\KeyExpireAt', + 'ttl' => 'Predis\Commands\KeyTimeToLive', + 'move' => 'Predis\Commands\KeyMove', + 'sort' => 'Predis\Commands\KeySort', /* commands operating on string values */ - 'set' => '\Predis\Commands\StringSet', - 'setnx' => '\Predis\Commands\StringSetPreserve', - 'mset' => '\Predis\Commands\StringSetMultiple', - 'msetnx' => '\Predis\Commands\StringSetMultiplePreserve', - 'get' => '\Predis\Commands\StringGet', - 'mget' => '\Predis\Commands\StringGetMultiple', - 'getset' => '\Predis\Commands\StringGetSet', - 'incr' => '\Predis\Commands\StringIncrement', - 'incrby' => '\Predis\Commands\StringIncrementBy', - 'decr' => '\Predis\Commands\StringDecrement', - 'decrby' => '\Predis\Commands\StringDecrementBy', + 'set' => 'Predis\Commands\StringSet', + 'setnx' => 'Predis\Commands\StringSetPreserve', + 'mset' => 'Predis\Commands\StringSetMultiple', + 'msetnx' => 'Predis\Commands\StringSetMultiplePreserve', + 'get' => 'Predis\Commands\StringGet', + 'mget' => 'Predis\Commands\StringGetMultiple', + 'getset' => 'Predis\Commands\StringGetSet', + 'incr' => 'Predis\Commands\StringIncrement', + 'incrby' => 'Predis\Commands\StringIncrementBy', + 'decr' => 'Predis\Commands\StringDecrement', + 'decrby' => 'Predis\Commands\StringDecrementBy', /* commands operating on lists */ - 'rpush' => '\Predis\Commands\ListPushTail', - 'lpush' => '\Predis\Commands\ListPushHead', - 'llen' => '\Predis\Commands\ListLength', - 'lrange' => '\Predis\Commands\ListRange', - 'ltrim' => '\Predis\Commands\ListTrim', - 'lindex' => '\Predis\Commands\ListIndex', - 'lset' => '\Predis\Commands\ListSet', - 'lrem' => '\Predis\Commands\ListRemove', - 'lpop' => '\Predis\Commands\ListPopFirst', - 'rpop' => '\Predis\Commands\ListPopLast', - 'rpoplpush' => '\Predis\Commands\ListPopLastPushHead', + 'rpush' => 'Predis\Commands\ListPushTail', + 'lpush' => 'Predis\Commands\ListPushHead', + 'llen' => 'Predis\Commands\ListLength', + 'lrange' => 'Predis\Commands\ListRange', + 'ltrim' => 'Predis\Commands\ListTrim', + 'lindex' => 'Predis\Commands\ListIndex', + 'lset' => 'Predis\Commands\ListSet', + 'lrem' => 'Predis\Commands\ListRemove', + 'lpop' => 'Predis\Commands\ListPopFirst', + 'rpop' => 'Predis\Commands\ListPopLast', + 'rpoplpush' => 'Predis\Commands\ListPopLastPushHead', /* commands operating on sets */ - 'sadd' => '\Predis\Commands\SetAdd', - 'srem' => '\Predis\Commands\SetRemove', - 'spop' => '\Predis\Commands\SetPop', - 'smove' => '\Predis\Commands\SetMove', - 'scard' => '\Predis\Commands\SetCardinality', - 'sismember' => '\Predis\Commands\SetIsMember', - 'sinter' => '\Predis\Commands\SetIntersection', - 'sinterstore' => '\Predis\Commands\SetIntersectionStore', - 'sunion' => '\Predis\Commands\SetUnion', - 'sunionstore' => '\Predis\Commands\SetUnionStore', - 'sdiff' => '\Predis\Commands\SetDifference', - 'sdiffstore' => '\Predis\Commands\SetDifferenceStore', - 'smembers' => '\Predis\Commands\SetMembers', - 'srandmember' => '\Predis\Commands\SetRandomMember', + 'sadd' => 'Predis\Commands\SetAdd', + 'srem' => 'Predis\Commands\SetRemove', + 'spop' => 'Predis\Commands\SetPop', + 'smove' => 'Predis\Commands\SetMove', + 'scard' => 'Predis\Commands\SetCardinality', + 'sismember' => 'Predis\Commands\SetIsMember', + 'sinter' => 'Predis\Commands\SetIntersection', + 'sinterstore' => 'Predis\Commands\SetIntersectionStore', + 'sunion' => 'Predis\Commands\SetUnion', + 'sunionstore' => 'Predis\Commands\SetUnionStore', + 'sdiff' => 'Predis\Commands\SetDifference', + 'sdiffstore' => 'Predis\Commands\SetDifferenceStore', + 'smembers' => 'Predis\Commands\SetMembers', + 'srandmember' => 'Predis\Commands\SetRandomMember', /* commands operating on sorted sets */ - 'zadd' => '\Predis\Commands\ZSetAdd', - 'zincrby' => '\Predis\Commands\ZSetIncrementBy', - 'zrem' => '\Predis\Commands\ZSetRemove', - 'zrange' => '\Predis\Commands\ZSetRange', - 'zrevrange' => '\Predis\Commands\ZSetReverseRange', - 'zrangebyscore' => '\Predis\Commands\ZSetRangeByScore', - 'zcard' => '\Predis\Commands\ZSetCardinality', - 'zscore' => '\Predis\Commands\ZSetScore', - 'zremrangebyscore' => '\Predis\Commands\ZSetRemoveRangeByScore', + 'zadd' => 'Predis\Commands\ZSetAdd', + 'zincrby' => 'Predis\Commands\ZSetIncrementBy', + 'zrem' => 'Predis\Commands\ZSetRemove', + 'zrange' => 'Predis\Commands\ZSetRange', + 'zrevrange' => 'Predis\Commands\ZSetReverseRange', + 'zrangebyscore' => 'Predis\Commands\ZSetRangeByScore', + 'zcard' => 'Predis\Commands\ZSetCardinality', + 'zscore' => 'Predis\Commands\ZSetScore', + 'zremrangebyscore' => 'Predis\Commands\ZSetRemoveRangeByScore', /* connection related commands */ - 'ping' => '\Predis\Commands\ConnectionPing', - 'auth' => '\Predis\Commands\ConnectionAuth', - 'select' => '\Predis\Commands\ConnectionSelect', - 'echo' => '\Predis\Commands\ConnectionEcho', - 'quit' => '\Predis\Commands\ConnectionQuit', + 'ping' => 'Predis\Commands\ConnectionPing', + 'auth' => 'Predis\Commands\ConnectionAuth', + 'select' => 'Predis\Commands\ConnectionSelect', + 'echo' => 'Predis\Commands\ConnectionEcho', + 'quit' => 'Predis\Commands\ConnectionQuit', /* remote server control commands */ - 'info' => '\Predis\Commands\ServerInfo', - 'slaveof' => '\Predis\Commands\ServerSlaveOf', - 'monitor' => '\Predis\Commands\ServerMonitor', - 'dbsize' => '\Predis\Commands\ServerDatabaseSize', - 'flushdb' => '\Predis\Commands\ServerFlushDatabase', - 'flushall' => '\Predis\Commands\ServerFlushAll', - 'save' => '\Predis\Commands\ServerSave', - 'bgsave' => '\Predis\Commands\ServerBackgroundSave', - 'lastsave' => '\Predis\Commands\ServerLastSave', - 'shutdown' => '\Predis\Commands\ServerShutdown', - 'bgrewriteaof' => '\Predis\Commands\ServerBackgroundRewriteAOF', + 'info' => 'Predis\Commands\ServerInfo', + 'slaveof' => 'Predis\Commands\ServerSlaveOf', + 'monitor' => 'Predis\Commands\ServerMonitor', + 'dbsize' => 'Predis\Commands\ServerDatabaseSize', + 'flushdb' => 'Predis\Commands\ServerFlushDatabase', + 'flushall' => 'Predis\Commands\ServerFlushAll', + 'save' => 'Predis\Commands\ServerSave', + 'bgsave' => 'Predis\Commands\ServerBackgroundSave', + 'lastsave' => 'Predis\Commands\ServerLastSave', + 'shutdown' => 'Predis\Commands\ServerShutdown', + 'bgrewriteaof' => 'Predis\Commands\ServerBackgroundRewriteAOF', /* ---------------- Redis 2.0 ---------------- */ /* commands operating on string values */ - 'setex' => '\Predis\Commands\StringSetExpire', - 'append' => '\Predis\Commands\StringAppend', - 'substr' => '\Predis\Commands\StringSubstr', + 'setex' => 'Predis\Commands\StringSetExpire', + 'append' => 'Predis\Commands\StringAppend', + 'substr' => 'Predis\Commands\StringSubstr', /* commands operating on lists */ - 'blpop' => '\Predis\Commands\ListPopFirstBlocking', - 'brpop' => '\Predis\Commands\ListPopLastBlocking', + 'blpop' => 'Predis\Commands\ListPopFirstBlocking', + 'brpop' => 'Predis\Commands\ListPopLastBlocking', /* commands operating on sorted sets */ - 'zunionstore' => '\Predis\Commands\ZSetUnionStore', - 'zinterstore' => '\Predis\Commands\ZSetIntersectionStore', - 'zcount' => '\Predis\Commands\ZSetCount', - 'zrank' => '\Predis\Commands\ZSetRank', - 'zrevrank' => '\Predis\Commands\ZSetReverseRank', - 'zremrangebyrank' => '\Predis\Commands\ZSetRemoveRangeByRank', + 'zunionstore' => 'Predis\Commands\ZSetUnionStore', + 'zinterstore' => 'Predis\Commands\ZSetIntersectionStore', + 'zcount' => 'Predis\Commands\ZSetCount', + 'zrank' => 'Predis\Commands\ZSetRank', + 'zrevrank' => 'Predis\Commands\ZSetReverseRank', + 'zremrangebyrank' => 'Predis\Commands\ZSetRemoveRangeByRank', /* commands operating on hashes */ - 'hset' => '\Predis\Commands\HashSet', - 'hsetnx' => '\Predis\Commands\HashSetPreserve', - 'hmset' => '\Predis\Commands\HashSetMultiple', - 'hincrby' => '\Predis\Commands\HashIncrementBy', - 'hget' => '\Predis\Commands\HashGet', - 'hmget' => '\Predis\Commands\HashGetMultiple', - 'hdel' => '\Predis\Commands\HashDelete', - 'hexists' => '\Predis\Commands\HashExists', - 'hlen' => '\Predis\Commands\HashLength', - 'hkeys' => '\Predis\Commands\HashKeys', - 'hvals' => '\Predis\Commands\HashValues', - 'hgetall' => '\Predis\Commands\HashGetAll', + 'hset' => 'Predis\Commands\HashSet', + 'hsetnx' => 'Predis\Commands\HashSetPreserve', + 'hmset' => 'Predis\Commands\HashSetMultiple', + 'hincrby' => 'Predis\Commands\HashIncrementBy', + 'hget' => 'Predis\Commands\HashGet', + 'hmget' => 'Predis\Commands\HashGetMultiple', + 'hdel' => 'Predis\Commands\HashDelete', + 'hexists' => 'Predis\Commands\HashExists', + 'hlen' => 'Predis\Commands\HashLength', + 'hkeys' => 'Predis\Commands\HashKeys', + 'hvals' => 'Predis\Commands\HashValues', + 'hgetall' => 'Predis\Commands\HashGetAll', /* transactions */ - 'multi' => '\Predis\Commands\TransactionMulti', - 'exec' => '\Predis\Commands\TransactionExec', - 'discard' => '\Predis\Commands\TransactionDiscard', + 'multi' => 'Predis\Commands\TransactionMulti', + 'exec' => 'Predis\Commands\TransactionExec', + 'discard' => 'Predis\Commands\TransactionDiscard', /* publish - subscribe */ - 'subscribe' => '\Predis\Commands\PubSubSubscribe', - 'unsubscribe' => '\Predis\Commands\PubSubUnsubscribe', - 'psubscribe' => '\Predis\Commands\PubSubSubscribeByPattern', - 'punsubscribe' => '\Predis\Commands\PubSubUnsubscribeByPattern', - 'publish' => '\Predis\Commands\PubSubPublish', + 'subscribe' => 'Predis\Commands\PubSubSubscribe', + 'unsubscribe' => 'Predis\Commands\PubSubUnsubscribe', + 'psubscribe' => 'Predis\Commands\PubSubSubscribeByPattern', + 'punsubscribe' => 'Predis\Commands\PubSubUnsubscribeByPattern', + 'publish' => 'Predis\Commands\PubSubPublish', /* remote server control commands */ - 'config' => '\Predis\Commands\ServerConfig', + 'config' => 'Predis\Commands\ServerConfig', ); } } diff --git a/lib/Predis/Profiles/ServerVersion22.php b/lib/Predis/Profiles/ServerVersion22.php index 34b8fd01..e49af0a9 100644 --- a/lib/Predis/Profiles/ServerVersion22.php +++ b/lib/Predis/Profiles/ServerVersion22.php @@ -35,170 +35,170 @@ class ServerVersion22 extends ServerProfile /* ---------------- Redis 1.2 ---------------- */ /* commands operating on the key space */ - 'exists' => '\Predis\Commands\KeyExists', - 'del' => '\Predis\Commands\KeyDelete', - 'type' => '\Predis\Commands\KeyType', - 'keys' => '\Predis\Commands\KeyKeys', - 'randomkey' => '\Predis\Commands\KeyRandom', - 'rename' => '\Predis\Commands\KeyRename', - 'renamenx' => '\Predis\Commands\KeyRenamePreserve', - 'expire' => '\Predis\Commands\KeyExpire', - 'expireat' => '\Predis\Commands\KeyExpireAt', - 'ttl' => '\Predis\Commands\KeyTimeToLive', - 'move' => '\Predis\Commands\KeyMove', - 'sort' => '\Predis\Commands\KeySort', + 'exists' => 'Predis\Commands\KeyExists', + 'del' => 'Predis\Commands\KeyDelete', + 'type' => 'Predis\Commands\KeyType', + 'keys' => 'Predis\Commands\KeyKeys', + 'randomkey' => 'Predis\Commands\KeyRandom', + 'rename' => 'Predis\Commands\KeyRename', + 'renamenx' => 'Predis\Commands\KeyRenamePreserve', + 'expire' => 'Predis\Commands\KeyExpire', + 'expireat' => 'Predis\Commands\KeyExpireAt', + 'ttl' => 'Predis\Commands\KeyTimeToLive', + 'move' => 'Predis\Commands\KeyMove', + 'sort' => 'Predis\Commands\KeySort', /* commands operating on string values */ - 'set' => '\Predis\Commands\StringSet', - 'setnx' => '\Predis\Commands\StringSetPreserve', - 'mset' => '\Predis\Commands\StringSetMultiple', - 'msetnx' => '\Predis\Commands\StringSetMultiplePreserve', - 'get' => '\Predis\Commands\StringGet', - 'mget' => '\Predis\Commands\StringGetMultiple', - 'getset' => '\Predis\Commands\StringGetSet', - 'incr' => '\Predis\Commands\StringIncrement', - 'incrby' => '\Predis\Commands\StringIncrementBy', - 'decr' => '\Predis\Commands\StringDecrement', - 'decrby' => '\Predis\Commands\StringDecrementBy', + 'set' => 'Predis\Commands\StringSet', + 'setnx' => 'Predis\Commands\StringSetPreserve', + 'mset' => 'Predis\Commands\StringSetMultiple', + 'msetnx' => 'Predis\Commands\StringSetMultiplePreserve', + 'get' => 'Predis\Commands\StringGet', + 'mget' => 'Predis\Commands\StringGetMultiple', + 'getset' => 'Predis\Commands\StringGetSet', + 'incr' => 'Predis\Commands\StringIncrement', + 'incrby' => 'Predis\Commands\StringIncrementBy', + 'decr' => 'Predis\Commands\StringDecrement', + 'decrby' => 'Predis\Commands\StringDecrementBy', /* commands operating on lists */ - 'rpush' => '\Predis\Commands\ListPushTail', - 'lpush' => '\Predis\Commands\ListPushHead', - 'llen' => '\Predis\Commands\ListLength', - 'lrange' => '\Predis\Commands\ListRange', - 'ltrim' => '\Predis\Commands\ListTrim', - 'lindex' => '\Predis\Commands\ListIndex', - 'lset' => '\Predis\Commands\ListSet', - 'lrem' => '\Predis\Commands\ListRemove', - 'lpop' => '\Predis\Commands\ListPopFirst', - 'rpop' => '\Predis\Commands\ListPopLast', - 'rpoplpush' => '\Predis\Commands\ListPopLastPushHead', + 'rpush' => 'Predis\Commands\ListPushTail', + 'lpush' => 'Predis\Commands\ListPushHead', + 'llen' => 'Predis\Commands\ListLength', + 'lrange' => 'Predis\Commands\ListRange', + 'ltrim' => 'Predis\Commands\ListTrim', + 'lindex' => 'Predis\Commands\ListIndex', + 'lset' => 'Predis\Commands\ListSet', + 'lrem' => 'Predis\Commands\ListRemove', + 'lpop' => 'Predis\Commands\ListPopFirst', + 'rpop' => 'Predis\Commands\ListPopLast', + 'rpoplpush' => 'Predis\Commands\ListPopLastPushHead', /* commands operating on sets */ - 'sadd' => '\Predis\Commands\SetAdd', - 'srem' => '\Predis\Commands\SetRemove', - 'spop' => '\Predis\Commands\SetPop', - 'smove' => '\Predis\Commands\SetMove', - 'scard' => '\Predis\Commands\SetCardinality', - 'sismember' => '\Predis\Commands\SetIsMember', - 'sinter' => '\Predis\Commands\SetIntersection', - 'sinterstore' => '\Predis\Commands\SetIntersectionStore', - 'sunion' => '\Predis\Commands\SetUnion', - 'sunionstore' => '\Predis\Commands\SetUnionStore', - 'sdiff' => '\Predis\Commands\SetDifference', - 'sdiffstore' => '\Predis\Commands\SetDifferenceStore', - 'smembers' => '\Predis\Commands\SetMembers', - 'srandmember' => '\Predis\Commands\SetRandomMember', + 'sadd' => 'Predis\Commands\SetAdd', + 'srem' => 'Predis\Commands\SetRemove', + 'spop' => 'Predis\Commands\SetPop', + 'smove' => 'Predis\Commands\SetMove', + 'scard' => 'Predis\Commands\SetCardinality', + 'sismember' => 'Predis\Commands\SetIsMember', + 'sinter' => 'Predis\Commands\SetIntersection', + 'sinterstore' => 'Predis\Commands\SetIntersectionStore', + 'sunion' => 'Predis\Commands\SetUnion', + 'sunionstore' => 'Predis\Commands\SetUnionStore', + 'sdiff' => 'Predis\Commands\SetDifference', + 'sdiffstore' => 'Predis\Commands\SetDifferenceStore', + 'smembers' => 'Predis\Commands\SetMembers', + 'srandmember' => 'Predis\Commands\SetRandomMember', /* commands operating on sorted sets */ - 'zadd' => '\Predis\Commands\ZSetAdd', - 'zincrby' => '\Predis\Commands\ZSetIncrementBy', - 'zrem' => '\Predis\Commands\ZSetRemove', - 'zrange' => '\Predis\Commands\ZSetRange', - 'zrevrange' => '\Predis\Commands\ZSetReverseRange', - 'zrangebyscore' => '\Predis\Commands\ZSetRangeByScore', - 'zcard' => '\Predis\Commands\ZSetCardinality', - 'zscore' => '\Predis\Commands\ZSetScore', - 'zremrangebyscore' => '\Predis\Commands\ZSetRemoveRangeByScore', + 'zadd' => 'Predis\Commands\ZSetAdd', + 'zincrby' => 'Predis\Commands\ZSetIncrementBy', + 'zrem' => 'Predis\Commands\ZSetRemove', + 'zrange' => 'Predis\Commands\ZSetRange', + 'zrevrange' => 'Predis\Commands\ZSetReverseRange', + 'zrangebyscore' => 'Predis\Commands\ZSetRangeByScore', + 'zcard' => 'Predis\Commands\ZSetCardinality', + 'zscore' => 'Predis\Commands\ZSetScore', + 'zremrangebyscore' => 'Predis\Commands\ZSetRemoveRangeByScore', /* connection related commands */ - 'ping' => '\Predis\Commands\ConnectionPing', - 'auth' => '\Predis\Commands\ConnectionAuth', - 'select' => '\Predis\Commands\ConnectionSelect', - 'echo' => '\Predis\Commands\ConnectionEcho', - 'quit' => '\Predis\Commands\ConnectionQuit', + 'ping' => 'Predis\Commands\ConnectionPing', + 'auth' => 'Predis\Commands\ConnectionAuth', + 'select' => 'Predis\Commands\ConnectionSelect', + 'echo' => 'Predis\Commands\ConnectionEcho', + 'quit' => 'Predis\Commands\ConnectionQuit', /* remote server control commands */ - 'info' => '\Predis\Commands\ServerInfo', - 'slaveof' => '\Predis\Commands\ServerSlaveOf', - 'monitor' => '\Predis\Commands\ServerMonitor', - 'dbsize' => '\Predis\Commands\ServerDatabaseSize', - 'flushdb' => '\Predis\Commands\ServerFlushDatabase', - 'flushall' => '\Predis\Commands\ServerFlushAll', - 'save' => '\Predis\Commands\ServerSave', - 'bgsave' => '\Predis\Commands\ServerBackgroundSave', - 'lastsave' => '\Predis\Commands\ServerLastSave', - 'shutdown' => '\Predis\Commands\ServerShutdown', - 'bgrewriteaof' => '\Predis\Commands\ServerBackgroundRewriteAOF', + 'info' => 'Predis\Commands\ServerInfo', + 'slaveof' => 'Predis\Commands\ServerSlaveOf', + 'monitor' => 'Predis\Commands\ServerMonitor', + 'dbsize' => 'Predis\Commands\ServerDatabaseSize', + 'flushdb' => 'Predis\Commands\ServerFlushDatabase', + 'flushall' => 'Predis\Commands\ServerFlushAll', + 'save' => 'Predis\Commands\ServerSave', + 'bgsave' => 'Predis\Commands\ServerBackgroundSave', + 'lastsave' => 'Predis\Commands\ServerLastSave', + 'shutdown' => 'Predis\Commands\ServerShutdown', + 'bgrewriteaof' => 'Predis\Commands\ServerBackgroundRewriteAOF', /* ---------------- Redis 2.0 ---------------- */ /* commands operating on string values */ - 'setex' => '\Predis\Commands\StringSetExpire', - 'append' => '\Predis\Commands\StringAppend', - 'substr' => '\Predis\Commands\StringSubstr', + 'setex' => 'Predis\Commands\StringSetExpire', + 'append' => 'Predis\Commands\StringAppend', + 'substr' => 'Predis\Commands\StringSubstr', /* commands operating on lists */ - 'blpop' => '\Predis\Commands\ListPopFirstBlocking', - 'brpop' => '\Predis\Commands\ListPopLastBlocking', + 'blpop' => 'Predis\Commands\ListPopFirstBlocking', + 'brpop' => 'Predis\Commands\ListPopLastBlocking', /* commands operating on sorted sets */ - 'zunionstore' => '\Predis\Commands\ZSetUnionStore', - 'zinterstore' => '\Predis\Commands\ZSetIntersectionStore', - 'zcount' => '\Predis\Commands\ZSetCount', - 'zrank' => '\Predis\Commands\ZSetRank', - 'zrevrank' => '\Predis\Commands\ZSetReverseRank', - 'zremrangebyrank' => '\Predis\Commands\ZSetRemoveRangeByRank', + 'zunionstore' => 'Predis\Commands\ZSetUnionStore', + 'zinterstore' => 'Predis\Commands\ZSetIntersectionStore', + 'zcount' => 'Predis\Commands\ZSetCount', + 'zrank' => 'Predis\Commands\ZSetRank', + 'zrevrank' => 'Predis\Commands\ZSetReverseRank', + 'zremrangebyrank' => 'Predis\Commands\ZSetRemoveRangeByRank', /* commands operating on hashes */ - 'hset' => '\Predis\Commands\HashSet', - 'hsetnx' => '\Predis\Commands\HashSetPreserve', - 'hmset' => '\Predis\Commands\HashSetMultiple', - 'hincrby' => '\Predis\Commands\HashIncrementBy', - 'hget' => '\Predis\Commands\HashGet', - 'hmget' => '\Predis\Commands\HashGetMultiple', - 'hdel' => '\Predis\Commands\HashDelete', - 'hexists' => '\Predis\Commands\HashExists', - 'hlen' => '\Predis\Commands\HashLength', - 'hkeys' => '\Predis\Commands\HashKeys', - 'hvals' => '\Predis\Commands\HashValues', - 'hgetall' => '\Predis\Commands\HashGetAll', + 'hset' => 'Predis\Commands\HashSet', + 'hsetnx' => 'Predis\Commands\HashSetPreserve', + 'hmset' => 'Predis\Commands\HashSetMultiple', + 'hincrby' => 'Predis\Commands\HashIncrementBy', + 'hget' => 'Predis\Commands\HashGet', + 'hmget' => 'Predis\Commands\HashGetMultiple', + 'hdel' => 'Predis\Commands\HashDelete', + 'hexists' => 'Predis\Commands\HashExists', + 'hlen' => 'Predis\Commands\HashLength', + 'hkeys' => 'Predis\Commands\HashKeys', + 'hvals' => 'Predis\Commands\HashValues', + 'hgetall' => 'Predis\Commands\HashGetAll', /* transactions */ - 'multi' => '\Predis\Commands\TransactionMulti', - 'exec' => '\Predis\Commands\TransactionExec', - 'discard' => '\Predis\Commands\TransactionDiscard', + 'multi' => 'Predis\Commands\TransactionMulti', + 'exec' => 'Predis\Commands\TransactionExec', + 'discard' => 'Predis\Commands\TransactionDiscard', /* publish - subscribe */ - 'subscribe' => '\Predis\Commands\PubSubSubscribe', - 'unsubscribe' => '\Predis\Commands\PubSubUnsubscribe', - 'psubscribe' => '\Predis\Commands\PubSubSubscribeByPattern', - 'punsubscribe' => '\Predis\Commands\PubSubUnsubscribeByPattern', - 'publish' => '\Predis\Commands\PubSubPublish', + 'subscribe' => 'Predis\Commands\PubSubSubscribe', + 'unsubscribe' => 'Predis\Commands\PubSubUnsubscribe', + 'psubscribe' => 'Predis\Commands\PubSubSubscribeByPattern', + 'punsubscribe' => 'Predis\Commands\PubSubUnsubscribeByPattern', + 'publish' => 'Predis\Commands\PubSubPublish', /* remote server control commands */ - 'config' => '\Predis\Commands\ServerConfig', + 'config' => 'Predis\Commands\ServerConfig', /* ---------------- Redis 2.2 ---------------- */ /* commands operating on the key space */ - 'persist' => '\Predis\Commands\KeyPersist', + 'persist' => 'Predis\Commands\KeyPersist', /* commands operating on string values */ - 'strlen' => '\Predis\Commands\StringStrlen', - 'setrange' => '\Predis\Commands\StringSetRange', - 'getrange' => '\Predis\Commands\StringGetRange', - 'setbit' => '\Predis\Commands\StringSetBit', - 'getbit' => '\Predis\Commands\StringGetBit', + 'strlen' => 'Predis\Commands\StringStrlen', + 'setrange' => 'Predis\Commands\StringSetRange', + 'getrange' => 'Predis\Commands\StringGetRange', + 'setbit' => 'Predis\Commands\StringSetBit', + 'getbit' => 'Predis\Commands\StringGetBit', /* commands operating on lists */ - 'rpushx' => '\Predis\Commands\ListPushTailX', - 'lpushx' => '\Predis\Commands\ListPushHeadX', - 'linsert' => '\Predis\Commands\ListInsert', - 'brpoplpush' => '\Predis\Commands\ListPopLastPushHeadBlocking', + 'rpushx' => 'Predis\Commands\ListPushTailX', + 'lpushx' => 'Predis\Commands\ListPushHeadX', + 'linsert' => 'Predis\Commands\ListInsert', + 'brpoplpush' => 'Predis\Commands\ListPopLastPushHeadBlocking', /* commands operating on sorted sets */ - 'zrevrangebyscore' => '\Predis\Commands\ZSetReverseRangeByScore', + 'zrevrangebyscore' => 'Predis\Commands\ZSetReverseRangeByScore', /* transactions */ - 'watch' => '\Predis\Commands\TransactionWatch', - 'unwatch' => '\Predis\Commands\TransactionUnwatch', + 'watch' => 'Predis\Commands\TransactionWatch', + 'unwatch' => 'Predis\Commands\TransactionUnwatch', /* remote server control commands */ - 'object' => '\Predis\Commands\ServerObject', - 'slowlog' => '\Predis\Commands\ServerSlowlog', + 'object' => 'Predis\Commands\ServerObject', + 'slowlog' => 'Predis\Commands\ServerSlowlog', ); } } diff --git a/lib/Predis/Profiles/ServerVersion24.php b/lib/Predis/Profiles/ServerVersion24.php index 173d1ad5..2617945e 100644 --- a/lib/Predis/Profiles/ServerVersion24.php +++ b/lib/Predis/Profiles/ServerVersion24.php @@ -35,176 +35,176 @@ class ServerVersion24 extends ServerProfile /* ---------------- Redis 1.2 ---------------- */ /* commands operating on the key space */ - 'exists' => '\Predis\Commands\KeyExists', - 'del' => '\Predis\Commands\KeyDelete', - 'type' => '\Predis\Commands\KeyType', - 'keys' => '\Predis\Commands\KeyKeys', - 'randomkey' => '\Predis\Commands\KeyRandom', - 'rename' => '\Predis\Commands\KeyRename', - 'renamenx' => '\Predis\Commands\KeyRenamePreserve', - 'expire' => '\Predis\Commands\KeyExpire', - 'expireat' => '\Predis\Commands\KeyExpireAt', - 'ttl' => '\Predis\Commands\KeyTimeToLive', - 'move' => '\Predis\Commands\KeyMove', - 'sort' => '\Predis\Commands\KeySort', + 'exists' => 'Predis\Commands\KeyExists', + 'del' => 'Predis\Commands\KeyDelete', + 'type' => 'Predis\Commands\KeyType', + 'keys' => 'Predis\Commands\KeyKeys', + 'randomkey' => 'Predis\Commands\KeyRandom', + 'rename' => 'Predis\Commands\KeyRename', + 'renamenx' => 'Predis\Commands\KeyRenamePreserve', + 'expire' => 'Predis\Commands\KeyExpire', + 'expireat' => 'Predis\Commands\KeyExpireAt', + 'ttl' => 'Predis\Commands\KeyTimeToLive', + 'move' => 'Predis\Commands\KeyMove', + 'sort' => 'Predis\Commands\KeySort', /* commands operating on string values */ - 'set' => '\Predis\Commands\StringSet', - 'setnx' => '\Predis\Commands\StringSetPreserve', - 'mset' => '\Predis\Commands\StringSetMultiple', - 'msetnx' => '\Predis\Commands\StringSetMultiplePreserve', - 'get' => '\Predis\Commands\StringGet', - 'mget' => '\Predis\Commands\StringGetMultiple', - 'getset' => '\Predis\Commands\StringGetSet', - 'incr' => '\Predis\Commands\StringIncrement', - 'incrby' => '\Predis\Commands\StringIncrementBy', - 'decr' => '\Predis\Commands\StringDecrement', - 'decrby' => '\Predis\Commands\StringDecrementBy', + 'set' => 'Predis\Commands\StringSet', + 'setnx' => 'Predis\Commands\StringSetPreserve', + 'mset' => 'Predis\Commands\StringSetMultiple', + 'msetnx' => 'Predis\Commands\StringSetMultiplePreserve', + 'get' => 'Predis\Commands\StringGet', + 'mget' => 'Predis\Commands\StringGetMultiple', + 'getset' => 'Predis\Commands\StringGetSet', + 'incr' => 'Predis\Commands\StringIncrement', + 'incrby' => 'Predis\Commands\StringIncrementBy', + 'decr' => 'Predis\Commands\StringDecrement', + 'decrby' => 'Predis\Commands\StringDecrementBy', /* commands operating on lists */ - 'rpush' => '\Predis\Commands\ListPushTail', - 'lpush' => '\Predis\Commands\ListPushHead', - 'llen' => '\Predis\Commands\ListLength', - 'lrange' => '\Predis\Commands\ListRange', - 'ltrim' => '\Predis\Commands\ListTrim', - 'lindex' => '\Predis\Commands\ListIndex', - 'lset' => '\Predis\Commands\ListSet', - 'lrem' => '\Predis\Commands\ListRemove', - 'lpop' => '\Predis\Commands\ListPopFirst', - 'rpop' => '\Predis\Commands\ListPopLast', - 'rpoplpush' => '\Predis\Commands\ListPopLastPushHead', + 'rpush' => 'Predis\Commands\ListPushTail', + 'lpush' => 'Predis\Commands\ListPushHead', + 'llen' => 'Predis\Commands\ListLength', + 'lrange' => 'Predis\Commands\ListRange', + 'ltrim' => 'Predis\Commands\ListTrim', + 'lindex' => 'Predis\Commands\ListIndex', + 'lset' => 'Predis\Commands\ListSet', + 'lrem' => 'Predis\Commands\ListRemove', + 'lpop' => 'Predis\Commands\ListPopFirst', + 'rpop' => 'Predis\Commands\ListPopLast', + 'rpoplpush' => 'Predis\Commands\ListPopLastPushHead', /* commands operating on sets */ - 'sadd' => '\Predis\Commands\SetAdd', - 'srem' => '\Predis\Commands\SetRemove', - 'spop' => '\Predis\Commands\SetPop', - 'smove' => '\Predis\Commands\SetMove', - 'scard' => '\Predis\Commands\SetCardinality', - 'sismember' => '\Predis\Commands\SetIsMember', - 'sinter' => '\Predis\Commands\SetIntersection', - 'sinterstore' => '\Predis\Commands\SetIntersectionStore', - 'sunion' => '\Predis\Commands\SetUnion', - 'sunionstore' => '\Predis\Commands\SetUnionStore', - 'sdiff' => '\Predis\Commands\SetDifference', - 'sdiffstore' => '\Predis\Commands\SetDifferenceStore', - 'smembers' => '\Predis\Commands\SetMembers', - 'srandmember' => '\Predis\Commands\SetRandomMember', + 'sadd' => 'Predis\Commands\SetAdd', + 'srem' => 'Predis\Commands\SetRemove', + 'spop' => 'Predis\Commands\SetPop', + 'smove' => 'Predis\Commands\SetMove', + 'scard' => 'Predis\Commands\SetCardinality', + 'sismember' => 'Predis\Commands\SetIsMember', + 'sinter' => 'Predis\Commands\SetIntersection', + 'sinterstore' => 'Predis\Commands\SetIntersectionStore', + 'sunion' => 'Predis\Commands\SetUnion', + 'sunionstore' => 'Predis\Commands\SetUnionStore', + 'sdiff' => 'Predis\Commands\SetDifference', + 'sdiffstore' => 'Predis\Commands\SetDifferenceStore', + 'smembers' => 'Predis\Commands\SetMembers', + 'srandmember' => 'Predis\Commands\SetRandomMember', /* commands operating on sorted sets */ - 'zadd' => '\Predis\Commands\ZSetAdd', - 'zincrby' => '\Predis\Commands\ZSetIncrementBy', - 'zrem' => '\Predis\Commands\ZSetRemove', - 'zrange' => '\Predis\Commands\ZSetRange', - 'zrevrange' => '\Predis\Commands\ZSetReverseRange', - 'zrangebyscore' => '\Predis\Commands\ZSetRangeByScore', - 'zcard' => '\Predis\Commands\ZSetCardinality', - 'zscore' => '\Predis\Commands\ZSetScore', - 'zremrangebyscore' => '\Predis\Commands\ZSetRemoveRangeByScore', + 'zadd' => 'Predis\Commands\ZSetAdd', + 'zincrby' => 'Predis\Commands\ZSetIncrementBy', + 'zrem' => 'Predis\Commands\ZSetRemove', + 'zrange' => 'Predis\Commands\ZSetRange', + 'zrevrange' => 'Predis\Commands\ZSetReverseRange', + 'zrangebyscore' => 'Predis\Commands\ZSetRangeByScore', + 'zcard' => 'Predis\Commands\ZSetCardinality', + 'zscore' => 'Predis\Commands\ZSetScore', + 'zremrangebyscore' => 'Predis\Commands\ZSetRemoveRangeByScore', /* connection related commands */ - 'ping' => '\Predis\Commands\ConnectionPing', - 'auth' => '\Predis\Commands\ConnectionAuth', - 'select' => '\Predis\Commands\ConnectionSelect', - 'echo' => '\Predis\Commands\ConnectionEcho', - 'quit' => '\Predis\Commands\ConnectionQuit', + 'ping' => 'Predis\Commands\ConnectionPing', + 'auth' => 'Predis\Commands\ConnectionAuth', + 'select' => 'Predis\Commands\ConnectionSelect', + 'echo' => 'Predis\Commands\ConnectionEcho', + 'quit' => 'Predis\Commands\ConnectionQuit', /* remote server control commands */ - 'info' => '\Predis\Commands\ServerInfo', - 'slaveof' => '\Predis\Commands\ServerSlaveOf', - 'monitor' => '\Predis\Commands\ServerMonitor', - 'dbsize' => '\Predis\Commands\ServerDatabaseSize', - 'flushdb' => '\Predis\Commands\ServerFlushDatabase', - 'flushall' => '\Predis\Commands\ServerFlushAll', - 'save' => '\Predis\Commands\ServerSave', - 'bgsave' => '\Predis\Commands\ServerBackgroundSave', - 'lastsave' => '\Predis\Commands\ServerLastSave', - 'shutdown' => '\Predis\Commands\ServerShutdown', - 'bgrewriteaof' => '\Predis\Commands\ServerBackgroundRewriteAOF', + 'info' => 'Predis\Commands\ServerInfo', + 'slaveof' => 'Predis\Commands\ServerSlaveOf', + 'monitor' => 'Predis\Commands\ServerMonitor', + 'dbsize' => 'Predis\Commands\ServerDatabaseSize', + 'flushdb' => 'Predis\Commands\ServerFlushDatabase', + 'flushall' => 'Predis\Commands\ServerFlushAll', + 'save' => 'Predis\Commands\ServerSave', + 'bgsave' => 'Predis\Commands\ServerBackgroundSave', + 'lastsave' => 'Predis\Commands\ServerLastSave', + 'shutdown' => 'Predis\Commands\ServerShutdown', + 'bgrewriteaof' => 'Predis\Commands\ServerBackgroundRewriteAOF', /* ---------------- Redis 2.0 ---------------- */ /* commands operating on string values */ - 'setex' => '\Predis\Commands\StringSetExpire', - 'append' => '\Predis\Commands\StringAppend', - 'substr' => '\Predis\Commands\StringSubstr', + 'setex' => 'Predis\Commands\StringSetExpire', + 'append' => 'Predis\Commands\StringAppend', + 'substr' => 'Predis\Commands\StringSubstr', /* commands operating on lists */ - 'blpop' => '\Predis\Commands\ListPopFirstBlocking', - 'brpop' => '\Predis\Commands\ListPopLastBlocking', + 'blpop' => 'Predis\Commands\ListPopFirstBlocking', + 'brpop' => 'Predis\Commands\ListPopLastBlocking', /* commands operating on sorted sets */ - 'zunionstore' => '\Predis\Commands\ZSetUnionStore', - 'zinterstore' => '\Predis\Commands\ZSetIntersectionStore', - 'zcount' => '\Predis\Commands\ZSetCount', - 'zrank' => '\Predis\Commands\ZSetRank', - 'zrevrank' => '\Predis\Commands\ZSetReverseRank', - 'zremrangebyrank' => '\Predis\Commands\ZSetRemoveRangeByRank', + 'zunionstore' => 'Predis\Commands\ZSetUnionStore', + 'zinterstore' => 'Predis\Commands\ZSetIntersectionStore', + 'zcount' => 'Predis\Commands\ZSetCount', + 'zrank' => 'Predis\Commands\ZSetRank', + 'zrevrank' => 'Predis\Commands\ZSetReverseRank', + 'zremrangebyrank' => 'Predis\Commands\ZSetRemoveRangeByRank', /* commands operating on hashes */ - 'hset' => '\Predis\Commands\HashSet', - 'hsetnx' => '\Predis\Commands\HashSetPreserve', - 'hmset' => '\Predis\Commands\HashSetMultiple', - 'hincrby' => '\Predis\Commands\HashIncrementBy', - 'hget' => '\Predis\Commands\HashGet', - 'hmget' => '\Predis\Commands\HashGetMultiple', - 'hdel' => '\Predis\Commands\HashDelete', - 'hexists' => '\Predis\Commands\HashExists', - 'hlen' => '\Predis\Commands\HashLength', - 'hkeys' => '\Predis\Commands\HashKeys', - 'hvals' => '\Predis\Commands\HashValues', - 'hgetall' => '\Predis\Commands\HashGetAll', + 'hset' => 'Predis\Commands\HashSet', + 'hsetnx' => 'Predis\Commands\HashSetPreserve', + 'hmset' => 'Predis\Commands\HashSetMultiple', + 'hincrby' => 'Predis\Commands\HashIncrementBy', + 'hget' => 'Predis\Commands\HashGet', + 'hmget' => 'Predis\Commands\HashGetMultiple', + 'hdel' => 'Predis\Commands\HashDelete', + 'hexists' => 'Predis\Commands\HashExists', + 'hlen' => 'Predis\Commands\HashLength', + 'hkeys' => 'Predis\Commands\HashKeys', + 'hvals' => 'Predis\Commands\HashValues', + 'hgetall' => 'Predis\Commands\HashGetAll', /* transactions */ - 'multi' => '\Predis\Commands\TransactionMulti', - 'exec' => '\Predis\Commands\TransactionExec', - 'discard' => '\Predis\Commands\TransactionDiscard', + 'multi' => 'Predis\Commands\TransactionMulti', + 'exec' => 'Predis\Commands\TransactionExec', + 'discard' => 'Predis\Commands\TransactionDiscard', /* publish - subscribe */ - 'subscribe' => '\Predis\Commands\PubSubSubscribe', - 'unsubscribe' => '\Predis\Commands\PubSubUnsubscribe', - 'psubscribe' => '\Predis\Commands\PubSubSubscribeByPattern', - 'punsubscribe' => '\Predis\Commands\PubSubUnsubscribeByPattern', - 'publish' => '\Predis\Commands\PubSubPublish', + 'subscribe' => 'Predis\Commands\PubSubSubscribe', + 'unsubscribe' => 'Predis\Commands\PubSubUnsubscribe', + 'psubscribe' => 'Predis\Commands\PubSubSubscribeByPattern', + 'punsubscribe' => 'Predis\Commands\PubSubUnsubscribeByPattern', + 'publish' => 'Predis\Commands\PubSubPublish', /* remote server control commands */ - 'config' => '\Predis\Commands\ServerConfig', + 'config' => 'Predis\Commands\ServerConfig', /* ---------------- Redis 2.2 ---------------- */ /* commands operating on the key space */ - 'persist' => '\Predis\Commands\KeyPersist', + 'persist' => 'Predis\Commands\KeyPersist', /* commands operating on string values */ - 'strlen' => '\Predis\Commands\StringStrlen', - 'setrange' => '\Predis\Commands\StringSetRange', - 'getrange' => '\Predis\Commands\StringGetRange', - 'setbit' => '\Predis\Commands\StringSetBit', - 'getbit' => '\Predis\Commands\StringGetBit', + 'strlen' => 'Predis\Commands\StringStrlen', + 'setrange' => 'Predis\Commands\StringSetRange', + 'getrange' => 'Predis\Commands\StringGetRange', + 'setbit' => 'Predis\Commands\StringSetBit', + 'getbit' => 'Predis\Commands\StringGetBit', /* commands operating on lists */ - 'rpushx' => '\Predis\Commands\ListPushTailX', - 'lpushx' => '\Predis\Commands\ListPushHeadX', - 'linsert' => '\Predis\Commands\ListInsert', - 'brpoplpush' => '\Predis\Commands\ListPopLastPushHeadBlocking', + 'rpushx' => 'Predis\Commands\ListPushTailX', + 'lpushx' => 'Predis\Commands\ListPushHeadX', + 'linsert' => 'Predis\Commands\ListInsert', + 'brpoplpush' => 'Predis\Commands\ListPopLastPushHeadBlocking', /* commands operating on sorted sets */ - 'zrevrangebyscore' => '\Predis\Commands\ZSetReverseRangeByScore', + 'zrevrangebyscore' => 'Predis\Commands\ZSetReverseRangeByScore', /* transactions */ - 'watch' => '\Predis\Commands\TransactionWatch', - 'unwatch' => '\Predis\Commands\TransactionUnwatch', + 'watch' => 'Predis\Commands\TransactionWatch', + 'unwatch' => 'Predis\Commands\TransactionUnwatch', /* remote server control commands */ - 'object' => '\Predis\Commands\ServerObject', - 'slowlog' => '\Predis\Commands\ServerSlowlog', + 'object' => 'Predis\Commands\ServerObject', + 'slowlog' => 'Predis\Commands\ServerSlowlog', /* ---------------- Redis 2.4 ---------------- */ /* remote server control commands */ - 'client' => '\Predis\Commands\ServerClient', + 'client' => 'Predis\Commands\ServerClient', ); } } diff --git a/lib/Predis/Profiles/ServerVersionNext.php b/lib/Predis/Profiles/ServerVersionNext.php index 8c890843..cec4547c 100644 --- a/lib/Predis/Profiles/ServerVersionNext.php +++ b/lib/Predis/Profiles/ServerVersionNext.php @@ -33,24 +33,24 @@ class ServerVersionNext extends ServerVersion24 { return array_merge(parent::getSupportedCommands(), array( /* commands operating on the key space */ - 'pttl' => '\Predis\Commands\KeyPreciseTimeToLive', - 'pexpire' => '\Predis\Commands\KeyPreciseExpire', - 'pexpireat' => '\Predis\Commands\KeyPreciseExpireAt', + 'pttl' => 'Predis\Commands\KeyPreciseTimeToLive', + 'pexpire' => 'Predis\Commands\KeyPreciseExpire', + 'pexpireat' => 'Predis\Commands\KeyPreciseExpireAt', /* commands operating on string values */ - 'psetex' => '\Predis\Commands\StringPreciseSetExpire', - 'incrbyfloat' => '\Predis\Commands\StringIncrementByFloat', + 'psetex' => 'Predis\Commands\StringPreciseSetExpire', + 'incrbyfloat' => 'Predis\Commands\StringIncrementByFloat', /* commands operating on hashes */ - 'hincrbyfloat' => '\Predis\Commands\HashIncrementByFloat', + 'hincrbyfloat' => 'Predis\Commands\HashIncrementByFloat', /* scripting */ - 'eval' => '\Predis\Commands\ServerEval', - 'evalsha' => '\Predis\Commands\ServerEvalSHA', - 'script' => '\Predis\Commands\ServerScript', + 'eval' => 'Predis\Commands\ServerEval', + 'evalsha' => 'Predis\Commands\ServerEvalSHA', + 'script' => 'Predis\Commands\ServerScript', /* remote server control commands */ - 'info' => '\Predis\Commands\ServerInfoV26x', + 'info' => 'Predis\Commands\ServerInfoV26x', )); } } diff --git a/lib/Predis/PubSub/DispatcherLoop.php b/lib/Predis/PubSub/DispatcherLoop.php index c7fab965..7bdd10cf 100644 --- a/lib/Predis/PubSub/DispatcherLoop.php +++ b/lib/Predis/PubSub/DispatcherLoop.php @@ -12,7 +12,6 @@ namespace Predis\PubSub; use Predis\Client; -use Predis\ClientException; /** * Method-dispatcher loop built around the client-side abstraction of a Redis @@ -46,7 +45,7 @@ class DispatcherLoop protected function validateCallback($callable) { if (!is_callable($callable)) { - throw new ClientException("A valid callable object must be provided"); + throw new \InvalidArgumentException("A valid callable object must be provided"); } } diff --git a/lib/Predis/PubSub/PubSubContext.php b/lib/Predis/PubSub/PubSubContext.php index 168634ee..03c95432 100644 --- a/lib/Predis/PubSub/PubSubContext.php +++ b/lib/Predis/PubSub/PubSubContext.php @@ -14,6 +14,7 @@ namespace Predis\PubSub; use Predis\Client; use Predis\Helpers; use Predis\ClientException; +use Predis\NotSupportedException; /** * Client-side abstraction of a Publish / Subscribe context. @@ -57,7 +58,7 @@ class PubSubContext implements \Iterator */ public function __destruct() { - $this->closeContext(); + $this->closeContext(true); } /** @@ -69,17 +70,12 @@ class PubSubContext implements \Iterator private function checkCapabilities(Client $client) { if (Helpers::isCluster($client->getConnection())) { - throw new ClientException( - 'Cannot initialize a PUB/SUB context over a cluster of connections' - ); + throw new NotSupportedException('Cannot initialize a PUB/SUB context over a cluster of connections'); } $commands = array('publish', 'subscribe', 'unsubscribe', 'psubscribe', 'punsubscribe'); - if ($client->getProfile()->supportsCommands($commands) === false) { - throw new ClientException( - 'The current profile does not support PUB/SUB related commands' - ); + throw new NotSupportedException('The current profile does not support PUB/SUB related commands'); } } @@ -150,10 +146,23 @@ class PubSubContext implements \Iterator /** * Closes the context by unsubscribing from all the subscribed channels. + * Optionally, the context can be forcefully closed by dropping the + * underlying connection. + * + * @param Boolean $force Forcefully close the context by closing the connection. + * @return Boolean Returns false if there are no pending messages. */ - public function closeContext() + public function closeContext($force = false) { - if ($this->valid()) { + if (!$this->valid()) { + return false; + } + + if ($force) { + $this->invalidate(); + $this->client->disconnect(); + } + else { if ($this->isFlagSet(self::STATUS_SUBSCRIBED)) { $this->unsubscribe(); } @@ -161,6 +170,8 @@ class PubSubContext implements \Iterator $this->punsubscribe(); } } + + return !$force; } /** @@ -208,7 +219,7 @@ class PubSubContext implements \Iterator */ public function next() { - if ($this->isFlagSet(self::STATUS_VALID)) { + if ($this->valid()) { $this->position++; } @@ -272,9 +283,8 @@ class PubSubContext implements \Iterator ); default: - throw new ClientException( - "Received an unknown message type {$response[0]} inside of a pubsub context" - ); + $message = "Received an unknown message type {$response[0]} inside of a pubsub context"; + throw new ClientException($message); } } } diff --git a/lib/Predis/Transaction/MultiExecContext.php b/lib/Predis/Transaction/MultiExecContext.php index 077e468e..f9020074 100644 --- a/lib/Predis/Transaction/MultiExecContext.php +++ b/lib/Predis/Transaction/MultiExecContext.php @@ -16,6 +16,7 @@ use Predis\Helpers; use Predis\ResponseQueued; use Predis\ClientException; use Predis\ServerException; +use Predis\NotSupportedException; use Predis\CommunicationException; use Predis\Protocol\ProtocolException; @@ -112,17 +113,12 @@ class MultiExecContext private function checkCapabilities(Client $client) { if (Helpers::isCluster($client->getConnection())) { - throw new ClientException( - 'Cannot initialize a MULTI/EXEC context over a cluster of connections' - ); + throw new NotSupportedException('Cannot initialize a MULTI/EXEC context over a cluster of connections'); } $profile = $client->getProfile(); - if ($profile->supportsCommands(array('multi', 'exec', 'discard')) === false) { - throw new ClientException( - 'The current profile does not support MULTI, EXEC and DISCARD' - ); + throw new NotSupportedException('The current profile does not support MULTI, EXEC and DISCARD'); } $this->canWatch = $profile->supportsCommands(array('watch', 'unwatch')); @@ -134,9 +130,7 @@ class MultiExecContext private function isWatchSupported() { if ($this->canWatch === false) { - throw new ClientException( - 'The current profile does not support WATCH and UNWATCH' - ); + throw new NotSupportedException('The current profile does not support WATCH and UNWATCH'); } } @@ -256,7 +250,7 @@ class MultiExecContext { $this->isWatchSupported(); $this->unflagState(self::STATE_WATCH); - $this->client->unwatch(); + $this->__call('unwatch', array()); return $this; } @@ -297,31 +291,23 @@ class MultiExecContext private function checkBeforeExecution($callable) { if ($this->checkState(self::STATE_INSIDEBLOCK)) { - throw new ClientException( - "Cannot invoke 'execute' or 'exec' inside an active client transaction block" - ); + throw new ClientException("Cannot invoke 'execute' or 'exec' inside an active client transaction block"); } if ($callable) { if (!is_callable($callable)) { - throw new \InvalidArgumentException( - 'Argument passed must be a callable object' - ); + throw new \InvalidArgumentException('Argument passed must be a callable object'); } if (count($this->commands) > 0) { $this->discard(); - throw new ClientException( - 'Cannot execute a transaction block after using fluent interface' - ); + throw new ClientException('Cannot execute a transaction block after using fluent interface'); } } if (isset($this->options['retry']) && !isset($callable)) { $this->discard(); - throw new \InvalidArgumentException( - 'Automatic retries can be used only when a transaction block is provided' - ); + throw new \InvalidArgumentException('Automatic retries can be used only when a transaction block is provided'); } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 3ab76c14..781b6e84 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,12 +1,24 @@ - + - test/ + tests/Predis/ + + + ext-phpiredis + ext-curl + realm-network-webdis + + + + + + + lib/Predis/ @@ -14,9 +26,14 @@ - - - - + + + + + + + + + diff --git a/test/ClientFeaturesTest.php b/test/ClientFeaturesTest.php deleted file mode 100644 index c275fb97..00000000 --- a/test/ClientFeaturesTest.php +++ /dev/null @@ -1,830 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class ClientFeaturesTestSuite extends PHPUnit_Framework_TestCase -{ - public $redis; - - protected function setUp() - { - $this->redis = RC::getConnection(); - $this->redis->flushdb(); - } - - protected function tearDown() - { - } - - protected function onNotSuccessfulTest(Exception $exception) - { - // drops and reconnect to a redis server on uncaught exceptions - RC::resetConnection(); - - parent::onNotSuccessfulTest($exception); - } - - /* Predis\ConnectionParameters */ - - function testConnectionParametersDefaultValues() - { - $params = new Predis\ConnectionParameters(); - - $this->assertEquals('127.0.0.1', $params->host); - $this->assertEquals(6379, $params->port); - $this->assertEquals(5, $params->connection_timeout); - $this->assertNull($params->read_write_timeout); - $this->assertNull($params->database); - $this->assertNull($params->password); - $this->assertNull($params->alias); - } - - function testConnectionParametersSetupValuesArray() - { - $paramsArray = RC::getConnectionParametersArgumentsArray(); - $params = new Predis\ConnectionParameters($paramsArray); - - $this->assertEquals($paramsArray['host'], $params->host); - $this->assertEquals($paramsArray['port'], $params->port); - $this->assertEquals($paramsArray['connection_timeout'], $params->connection_timeout); - $this->assertEquals($paramsArray['read_write_timeout'], $params->read_write_timeout); - $this->assertEquals($paramsArray['database'], $params->database); - $this->assertEquals($paramsArray['password'], $params->password); - $this->assertEquals($paramsArray['alias'], $params->alias); - } - - function testConnectionParametersSetupValuesString() - { - $paramsArray = RC::getConnectionParametersArgumentsArray(); - $paramsString = RC::getConnectionParametersArgumentsString($paramsArray); - $params = new Predis\ConnectionParameters($paramsArray); - - $this->assertEquals($paramsArray['host'], $params->host); - $this->assertEquals($paramsArray['port'], $params->port); - $this->assertEquals($paramsArray['connection_timeout'], $params->connection_timeout); - $this->assertEquals($paramsArray['read_write_timeout'], $params->read_write_timeout); - $this->assertEquals($paramsArray['database'], $params->database); - $this->assertEquals($paramsArray['password'], $params->password); - $this->assertEquals($paramsArray['alias'], $params->alias); - } - - /* Predis\Commands\Command and derivates */ - - function testCommand_TestArguments() - { - $cmdArgs = array('key1', 'key2', 'key3'); - - $cmd = new Predis\Commands\StringGetMultiple(); - $cmd->setArguments($cmdArgs); - $this->assertEquals($cmdArgs[0], $cmd->getArgument(0)); - $this->assertEquals($cmdArgs[1], $cmd->getArgument(1)); - $this->assertEquals($cmdArgs[2], $cmd->getArgument(2)); - - $cmd = new Predis\Commands\ConnectionPing(); - $this->assertNull($cmd->getArgument(0)); - } - - function testCommand_ParseResponse() - { - // default parser - $cmd = new Predis\Commands\StringGet(); - $this->assertEquals('test', $cmd->parseResponse('test')); - - // overridden parser (boolean) - $cmd = new Predis\Commands\KeyExists(); - $this->assertTrue($cmd->parseResponse('1')); - $this->assertFalse($cmd->parseResponse('0')); - - // overridden parser (boolean) - $cmd = new Predis\Commands\ConnectionPing(); - $this->assertTrue($cmd->parseResponse('PONG')); - - // overridden parser (complex) - // TODO: emulate a respons to INFO - } - - - /* Predis\Profiles\ServerProfile and derivates */ - - function testServerProfile_GetSpecificVersions() - { - $this->assertInstanceOf('\Predis\Profiles\ServerVersion12', Predis\Profiles\ServerProfile::get('1.2')); - $this->assertInstanceOf('\Predis\Profiles\ServerVersion20', Predis\Profiles\ServerProfile::get('2.0')); - $this->assertInstanceOf('\Predis\Profiles\ServerVersion22', Predis\Profiles\ServerProfile::get('2.2')); - $this->assertInstanceOf('\Predis\Profiles\ServerVersionNext', Predis\Profiles\ServerProfile::get('dev')); - $this->assertInstanceOf('\Predis\Profiles\ServerProfile', Predis\Profiles\ServerProfile::get('default')); - $this->assertEquals(Predis\Profiles\ServerProfile::get('default'), Predis\Profiles\ServerProfile::getDefault()); - } - - function testServerProfile_SupportedCommands() - { - $profile_12 = Predis\Profiles\ServerProfile::get('1.2'); - $profile_20 = Predis\Profiles\ServerProfile::get('2.0'); - - $this->assertTrue($profile_12->supportsCommand('info')); - $this->assertTrue($profile_20->supportsCommand('info')); - - $this->assertFalse($profile_12->supportsCommand('multi')); - $this->assertTrue($profile_20->supportsCommand('multi')); - - $this->assertFalse($profile_12->supportsCommand('watch')); - $this->assertFalse($profile_20->supportsCommand('watch')); - } - - function testServerProfile_CommandsCreation() - { - $profile = Predis\Profiles\ServerProfile::get('2.0'); - - $cmdNoArgs = $profile->createCommand('info'); - $this->assertInstanceOf('\Predis\Commands\ServerInfo', $cmdNoArgs); - $this->assertNull($cmdNoArgs->getArgument()); - - $args = array('key1', 'key2'); - $cmdWithArgs = $profile->createCommand('mget', $args); - - $this->assertInstanceOf('\Predis\Commands\StringGetMultiple', $cmdWithArgs); - $this->assertEquals($args[0], $cmdWithArgs->getArgument()); // TODO: why? - $this->assertEquals($args[0], $cmdWithArgs->getArgument(0)); - $this->assertEquals($args[1], $cmdWithArgs->getArgument(1)); - - $bogusCommand = 'not_existing_command'; - $expectedMessage = "'$bogusCommand' is not a registered Redis command"; - RC::testForClientException($this, $expectedMessage, function() - use($profile, $bogusCommand) { - - $profile->createCommand($bogusCommand); - }); - } - - function testServerProfile_CommandsRegistration() - { - $profile = Predis\Profiles\ServerProfile::get('1.2'); - $cmdId = 'multi'; - $cmdClass = '\Predis\Commands\TransactionMulti'; - - $this->assertFalse($profile->supportsCommand($cmdId)); - $profile->defineCommand($cmdId, new $cmdClass()); - $this->assertTrue($profile->supportsCommand($cmdId)); - $this->assertInstanceOf($cmdClass, $profile->createCommand($cmdId)); - } - - function testServerProfile_CaseInsensitiveCommandsNames() { - $profile = $this->redis->getProfile(); - - $uppercase = $profile->supportsCommand('INFO'); - $lowercase = $profile->supportsCommand('info'); - $this->assertEquals($uppercase, $lowercase); - - $uppercase = $profile->createCommand('INFO'); - $lowercase = $profile->createCommand('info'); - $this->assertEquals($uppercase, $lowercase); - } - - /* Predis\ResponseQueued */ - - function testResponseQueued() - { - $response = new Predis\ResponseQueued(); - $this->assertInstanceOf('\Predis\IReplyObject', $response); - $this->assertEquals(\Predis\Protocol\Text\TextProtocol::QUEUED, (string)$response); - } - - /* Predis\ResponseError */ - - function testResponseError() - { - $errorMessage = 'ERROR MESSAGE'; - $response = new Predis\ResponseError($errorMessage); - - $this->assertInstanceOf('\Predis\IReplyObject', $response); - $this->assertInstanceOf('\Predis\IRedisServerError', $response); - - $this->assertEquals($errorMessage, $response->getMessage()); - $this->assertEquals($errorMessage, (string)$response); - } - - /* Predis\Network\StreamConnection */ - - function testStreamConnection_StringCastReturnsIPAndPort() - { - $connection = new Predis\Network\StreamConnection(RC::getConnectionParameters()); - $this->assertEquals(RC::SERVER_HOST . ':' . RC::SERVER_PORT, (string) $connection); - } - - function testStreamConnection_ConnectDisconnect() - { - $connection = new Predis\Network\StreamConnection(RC::getConnectionParameters()); - - $this->assertFalse($connection->isConnected()); - $connection->connect(); - $this->assertTrue($connection->isConnected()); - $connection->disconnect(); - $this->assertFalse($connection->isConnected()); - } - - function testStreamConnection_WriteAndReadCommand() - { - $cmd = Predis\Profiles\ServerProfile::getDefault()->createCommand('ping'); - $connection = new Predis\Network\StreamConnection(RC::getConnectionParameters()); - $connection->connect(); - - $connection->writeCommand($cmd); - $this->assertTrue($connection->readResponse($cmd)); - } - - function testStreamConnection_WriteCommandAndCloseConnection() - { - $cmd = Predis\Profiles\ServerProfile::getDefault()->createCommand('quit'); - $connection = new Predis\Network\StreamConnection(new Predis\ConnectionParameters( - RC::getConnectionArguments() + array('read_write_timeout' => 0.5) - )); - - $connection->connect(); - - $this->assertTrue($connection->isConnected()); - - $connection->writeCommand($cmd); - $connection->disconnect(); - - $exceptionMessage = 'Error while reading line from the server'; - RC::testForCommunicationException($this, $exceptionMessage, function() use($connection, $cmd) { - $connection->readResponse($cmd); - }); - } - - function testStreamConnection_GetSocketOpensConnection() - { - $connection = new Predis\Network\StreamConnection(RC::getConnectionParameters()); - - $this->assertFalse($connection->isConnected()); - $this->assertInternalType('resource', $connection->getResource()); - $this->assertTrue($connection->isConnected()); - } - - function testStreamConnection_LazyConnect() - { - $cmd = Predis\Profiles\ServerProfile::getDefault()->createCommand('ping'); - $connection = new Predis\Network\StreamConnection(RC::getConnectionParameters()); - - $this->assertFalse($connection->isConnected()); - - $connection->writeCommand($cmd); - - $this->assertTrue($connection->isConnected()); - $this->assertTrue($connection->readResponse($cmd)); - } - - function testStreamConnection_Alias() - { - $connection1 = new Predis\Network\StreamConnection(RC::getConnectionParameters()); - $this->assertNull($connection1->getParameters()->alias); - - $args = array_merge(RC::getConnectionArguments(), array('alias' => 'servername')); - $connection2 = new Predis\Network\StreamConnection(new Predis\ConnectionParameters($args)); - - $this->assertEquals('servername', $connection2->getParameters()->alias); - } - - function testStreamConnection_ConnectionTimeout() - { - $timeout = 3; - $args = array('host' => '1.0.0.1', 'connection_timeout' => $timeout); - $connection = new Predis\Network\StreamConnection(new Predis\ConnectionParameters($args)); - - $start = time(); - RC::testForCommunicationException($this, null, function() use($connection) { - $connection->connect(); - }); - - $this->assertEquals((float)(time() - $start), $timeout, '', 1); - } - - function testStreamConnection_ReadTimeout() - { - $timeout = 1; - $args = array_merge(RC::getConnectionArguments(), array('read_write_timeout' => $timeout)); - $cmdFake = Predis\Profiles\ServerProfile::getDefault()->createCommand('ping'); - $connection = new Predis\Network\StreamConnection(new Predis\ConnectionParameters($args)); - - $expectedMessage = 'Error while reading line from the server'; - $start = time(); - RC::testForCommunicationException($this, $expectedMessage, function() use($connection, $cmdFake) { - $connection->readResponse($cmdFake); - }); - $this->assertEquals((float)(time() - $start), $timeout, '', 1); - } - - /* Predis\Protocol\TextResponseReader */ - - function testResponseReader_OptionIterableMultiBulkReplies() - { - $protocol = new Predis\Protocol\Text\ComposableTextProtocol(); - $reader = $protocol->getReader(); - $connection = new Predis\Network\ComposableStreamConnection(RC::getConnectionParameters(), $protocol); - - $reader->setHandler( - Predis\Protocol\Text\TextProtocol::PREFIX_MULTI_BULK, - new Predis\Protocol\Text\ResponseMultiBulkHandler() - ); - $connection->writeBytes("KEYS *\r\n"); - $this->assertInternalType('array', $reader->read($connection)); - - $reader->setHandler( - Predis\Protocol\Text\TextProtocol::PREFIX_MULTI_BULK, - new Predis\Protocol\Text\ResponseMultiBulkStreamHandler() - ); - $connection->writeBytes("KEYS *\r\n"); - $this->assertInstanceOf('\Iterator', $reader->read($connection)); - } - - function testResponseReader_OptionExceptionOnError() - { - $protocol = new Predis\Protocol\Text\ComposableTextProtocol(); - $reader = $protocol->getReader(); - $connection = new Predis\Network\ComposableStreamConnection(RC::getConnectionParameters(), $protocol); - - $rawCmdUnexpected = "*3\r\n$5\r\nLPUSH\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"; - $connection->writeBytes("*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"); - $reader->read($connection); - - $reader->setHandler( - Predis\Protocol\Text\TextProtocol::PREFIX_ERROR, - new Predis\Protocol\Text\ResponseErrorSilentHandler() - ); - $connection->writeBytes($rawCmdUnexpected); - $errorReply = $reader->read($connection); - $this->assertInstanceOf('\Predis\ResponseError', $errorReply); - $this->assertEquals(RC::EXCEPTION_WRONG_TYPE, $errorReply->getMessage()); - - $reader->setHandler( - Predis\Protocol\Text\TextProtocol::PREFIX_ERROR, - new Predis\Protocol\Text\ResponseErrorHandler() - ); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function() - use ($connection, $rawCmdUnexpected) { - - $connection->writeBytes($rawCmdUnexpected); - $connection->getProtocol()->read($connection); - }); - } - - function testResponseReader_EmptyBulkResponse() - { - $protocol = new Predis\Protocol\Text\ComposableTextProtocol(); - $connection = new Predis\Network\ComposableStreamConnection(RC::getConnectionParameters(), $protocol); - $client = new Predis\Client($connection); - - $this->assertTrue($client->set('foo', '')); - $this->assertEquals('', $client->get('foo')); - $this->assertEquals('', $client->get('foo')); - } - - /* Client initialization */ - - function testClientInitialization_SingleConnectionParameters() - { - $params1 = array_merge(RC::getConnectionArguments(), array( - 'connection_timeout' => 10, - 'read_write_timeout' => 30, - 'alias' => 'connection_alias', - )); - $params2 = RC::getConnectionParametersArgumentsString($params1); - $params3 = new Predis\ConnectionParameters($params1); - $params4 = new Predis\Network\StreamConnection($params3); - - foreach (array($params1, $params2, $params3, $params4) as $params) { - $client = new Predis\Client($params); - $parameters = $client->getConnection()->getParameters(); - $this->assertEquals($params1['host'], $parameters->host); - $this->assertEquals($params1['port'], $parameters->port); - $this->assertEquals($params1['connection_timeout'], $parameters->connection_timeout); - $this->assertEquals($params1['read_write_timeout'], $parameters->read_write_timeout); - $this->assertEquals($params1['alias'], $parameters->alias); - $this->assertNull($parameters->password); - } - } - - function testClientInitialization_ClusterConnectionParameters() - { - $params1 = array_merge(RC::getConnectionArguments(), array( - 'connection_timeout' => 10, - 'read_write_timeout' => 30, - )); - $params2 = RC::getConnectionParametersArgumentsString($params1); - $params3 = new Predis\ConnectionParameters($params1); - $params4 = new Predis\Network\StreamConnection($params3); - - $client1 = new Predis\Client(array($params1, $params2, $params3, $params4)); - - foreach ($client1->getConnection() as $connection) { - $parameters = $connection->getParameters(); - $this->assertEquals($params1['host'], $parameters->host); - $this->assertEquals($params1['port'], $parameters->port); - $this->assertEquals($params1['connection_timeout'], $parameters->connection_timeout); - $this->assertEquals($params1['read_write_timeout'], $parameters->read_write_timeout); - $this->assertNull($parameters->password); - } - - $connectionCluster = $client1->getConnection(); - $client2 = new Predis\Client($connectionCluster); - $this->assertSame($connectionCluster, $client2->getConnection()); - } - - /* Client + PipelineContext */ - - function testPipelineContext_Simple() - { - $client = RC::getConnection(); - $client->flushdb(); - - $pipe = $client->pipeline(); - $pipelineClass = '\Predis\Pipeline\PipelineContext'; - - $this->assertInstanceOf($pipelineClass, $pipe); - $this->assertInstanceOf($pipelineClass, $pipe->set('foo', 'bar')); - $this->assertInstanceOf($pipelineClass, $pipe->set('hoge', 'piyo')); - $this->assertInstanceOf($pipelineClass, $pipe->mset(array( - 'foofoo' => 'barbar', 'hogehoge' => 'piyopiyo' - ))); - $this->assertInstanceOf($pipelineClass, $pipe->mget(array( - 'foo', 'hoge', 'foofoo', 'hogehoge' - ))); - - $replies = $pipe->execute(); - $this->assertInternalType('array', $replies); - $this->assertEquals(4, count($replies)); - $this->assertEquals(4, count($replies[3])); - $this->assertEquals('barbar', $replies[3][2]); - } - - function testPipelineContext_FluentInterface() - { - $client = RC::getConnection(); - $client->flushdb(); - - $replies = $client->pipeline()->ping()->set('foo', 'bar')->get('foo')->execute(); - $this->assertInternalType('array', $replies); - $this->assertEquals('bar', $replies[2]); - } - - function testPipelineContext_CallableAnonymousBlock() - { - $client = RC::getConnection(); - $client->flushdb(); - - $replies = $client->pipeline(function($pipe) { - $pipe->ping(); - $pipe->set('foo', 'bar'); - $pipe->get('foo'); - }); - - $this->assertInternalType('array', $replies); - $this->assertEquals('bar', $replies[2]); - } - - function testPipelineContext_ClientExceptionInCallableBlock() - { - $client = RC::getConnection(); - $client->flushdb(); - - RC::testForClientException($this, 'TEST', function() use($client) { - $client->pipeline(function($pipe) { - $pipe->ping(); - $pipe->set('foo', 'bar'); - throw new Predis\ClientException("TEST"); - }); - }); - - $this->assertFalse($client->exists('foo')); - } - - function testPipelineContext_ServerExceptionInCallableBlock() - { - $client = RC::createConnection(array('throw_errors' => false)); - $client->flushdb(); - - $replies = $client->pipeline(function($pipe) { - $pipe->set('foo', 'bar'); - $pipe->lpush('foo', 'piyo'); // LIST operation on STRING type returns an ERROR - $pipe->set('hoge', 'piyo'); - }); - - $this->assertInternalType('array', $replies); - $this->assertInstanceOf('\Predis\ResponseError', $replies[1]); - $this->assertTrue($client->exists('foo')); - $this->assertTrue($client->exists('hoge')); - } - - function testPipelineContext_Flush() - { - $client = RC::getConnection(); - $client->flushdb(); - - $pipe = $client->pipeline(); - $pipe->set('foo', 'bar')->set('hoge', 'piyo'); - $pipe->flushPipeline(); - $pipe->ping()->mget(array('foo', 'hoge')); - $replies = $pipe->execute(); - - $this->assertInternalType('array', $replies); - $this->assertEquals(4, count($replies)); - $this->assertEquals('bar', $replies[3][0]); - $this->assertEquals('piyo', $replies[3][1]); - } - - /* Predis\Client + Predis\MultiExecContext */ - - function testMultiExecContext_Simple() - { - $client = RC::getConnection(); - $client->flushdb(); - - $multi = $client->multiExec(); - $transactionClass = '\Predis\Transaction\MultiExecContext'; - - $this->assertInstanceOf($transactionClass, $multi); - $this->assertInstanceOf($transactionClass, $multi->set('foo', 'bar')); - $this->assertInstanceOf($transactionClass, $multi->set('hoge', 'piyo')); - $this->assertInstanceOf($transactionClass, $multi->mset(array( - 'foofoo' => 'barbar', 'hogehoge' => 'piyopiyo' - ))); - $this->assertInstanceOf($transactionClass, $multi->mget(array( - 'foo', 'hoge', 'foofoo', 'hogehoge' - ))); - - $replies = $multi->execute(); - $this->assertInternalType('array', $replies); - $this->assertEquals(4, count($replies)); - $this->assertEquals(4, count($replies[3])); - $this->assertEquals('barbar', $replies[3][2]); - } - - function testMultiExecContext_FluentInterface() - { - $client = RC::getConnection(); - $client->flushdb(); - - $replies = $client->multiExec()->ping()->set('foo', 'bar')->get('foo')->execute(); - $this->assertInternalType('array', $replies); - $this->assertEquals('bar', $replies[2]); - } - - function testMultiExecContext_CallableAnonymousBlock() - { - $client = RC::getConnection(); - $client->flushdb(); - - $replies = $client->multiExec(function($multi) { - $multi->ping(); - $multi->set('foo', 'bar'); - $multi->get('foo'); - }); - - $this->assertInternalType('array', $replies); - $this->assertEquals('bar', $replies[2]); - } - - /** - * @expectedException Predis\ClientException - */ - function testMultiExecContext_CannotMixFluentInterfaceAndAnonymousBlock() - { - $emptyBlock = function($tx) { }; - $tx = RC::getConnection()->multiExec()->get('foo')->execute($emptyBlock); - } - - function testMultiExecContext_EmptyCallableBlock() - { - $client = RC::getConnection(); - $client->flushdb(); - - $replies = $client->multiExec(function($multi) { }); - $this->assertEquals(0, count($replies)); - - $options = array('cas' => true); - $replies = $client->multiExec($options, function($multi) { }); - $this->assertEquals(0, count($replies)); - - $options = array('cas' => true); - $replies = $client->multiExec($options, function($multi) { - $multi->multi(); - }); - $this->assertEquals(0, count($replies)); - } - - function testMultiExecContext_ClientExceptionInCallableBlock() - { - $client = RC::getConnection(); - $client->flushdb(); - - RC::testForClientException($this, 'TEST', function() use($client) { - $client->multiExec(function($multi) { - $multi->ping(); - $multi->set('foo', 'bar'); - throw new Predis\ClientException("TEST"); - }); - }); - - $this->assertFalse($client->exists('foo')); - } - - function testMultiExecContext_ServerExceptionInCallableBlock() - { - $client = RC::createConnection(array('throw_errors' => false)); - $client->flushdb(); - - $replies = $client->multiExec(function($multi) { - $multi->set('foo', 'bar'); - $multi->lpush('foo', 'piyo'); // LIST operation on STRING type returns an ERROR - $multi->set('hoge', 'piyo'); - }); - - $this->assertInternalType('array', $replies); - $this->assertInstanceOf('\Predis\ResponseError', $replies[1]); - $this->assertTrue($client->exists('foo')); - $this->assertTrue($client->exists('hoge')); - } - - function testMultiExecContext_Discard() - { - $client = RC::getConnection(); - $client->flushdb(); - - $replies = $client->multiExec(function($multi) { - $multi->set('foo', 'bar'); - $multi->discard(); - $multi->set('hoge', 'piyo'); - }); - - $this->assertEquals(1, count($replies)); - $this->assertFalse($client->exists('foo')); - $this->assertTrue($client->exists('hoge')); - } - - function testMultiExecContext_DiscardEmpty() - { - $client = RC::getConnection(); - $client->flushdb(); - - $replies = $client->multiExec(function($multi) { - $multi->discard(); - }); - - $this->assertEquals(0, count($replies)); - } - - function testMultiExecContext_Watch() - { - $client1 = RC::getConnection(); - $client2 = RC::getConnection(true); - $client1->flushdb(); - - RC::testForAbortedMultiExecException($this, function() - use($client1, $client2) { - - $client1->multiExec(array('watch' => 'sentinel'), function($multi) - use ($client2) { - - $multi->set('sentinel', 'client1'); - $multi->get('sentinel'); - $client2->set('sentinel', 'client2'); - }); - }); - - $this->assertEquals('client2', $client1->get('sentinel')); - } - - function testMultiExecContext_CheckAndSet() - { - $client = RC::getConnection(); - $client->flushdb(); - $client->set('foo', 'bar'); - - $options = array('watch' => 'foo', 'cas' => true); - $replies = $client->multiExec($options, function($tx) { - $tx->watch('foobar'); - $foo = $tx->get('foo'); - $tx->multi(); - $tx->set('foobar', $foo); - $tx->mget('foo', 'foobar'); - }); - $this->assertInternalType('array', $replies); - $this->assertEquals(array(true, array('bar', 'bar')), $replies); - - $tx = $client->multiExec($options); - $tx->watch('foobar'); - $foo = $tx->get('foo'); - $replies = $tx->multi() - ->set('foobar', $foo) - ->mget('foo', 'foobar') - ->execute(); - $this->assertInternalType('array', $replies); - $this->assertEquals(array(true, array('bar', 'bar')), $replies); - } - - function testMultiExecContext_RetryOnServerAbort() - { - $client1 = RC::getConnection(); - $client2 = RC::getConnection(true); - $client1->flushdb(); - - $retry = 3; - $attempts = 0; - RC::testForAbortedMultiExecException($this, function() - use($client1, $client2, $retry, &$attempts) { - - $options = array('watch' => 'sentinel', 'retry' => $retry); - $client1->multiExec($options, function($tx) - use ($client2, &$attempts) { - - $attempts++; - $tx->set('sentinel', 'client1'); - $tx->get('sentinel'); - $client2->set('sentinel', 'client2'); - }); - }); - $this->assertEquals('client2', $client1->get('sentinel')); - $this->assertEquals($retry + 1, $attempts); - - $retry = 3; - $attempts = 0; - RC::testForAbortedMultiExecException($this, function() - use($client1, $client2, $retry, &$attempts) { - - $options = array( - 'watch' => 'sentinel', - 'cas' => true, - 'retry' => $retry - ); - $client1->multiExec($options, function($tx) - use ($client2, &$attempts) { - - $attempts++; - $tx->incr('attempts'); - $tx->multi(); - $tx->set('sentinel', 'client1'); - $tx->get('sentinel'); - $client2->set('sentinel', 'client2'); - }); - }); - $this->assertEquals('client2', $client1->get('sentinel')); - $this->assertEquals($retry + 1, $attempts); - $this->assertEquals($attempts, $client1->get('attempts')); - } - - /** - * @expectedException InvalidArgumentException - */ - function testMultiExecContext_RetryNotAvailableWithoutBlock() - { - $options = array('watch' => 'foo', 'retry' => 1); - $tx = RC::getConnection()->multiExec($options); - $tx->multi()->get('foo')->exec(); - } - - function testMultiExecContext_CheckAndSet_Discard() - { - $client = RC::getConnection(); - $client->flushdb(); - - $client->set('foo', 'bar'); - $options = array('watch' => 'foo', 'cas' => true); - $replies = $client->multiExec($options, function($tx) { - $tx->watch('foobar'); - $foo = $tx->get('foo'); - $tx->multi(); - $tx->set('foobar', $foo); - $tx->discard(); - $tx->mget('foo', 'foobar'); - }); - $this->assertInternalType('array', $replies); - $this->assertEquals(array(array('bar', null)), $replies); - - $hijack = true; - $client->set('foo', 'bar'); - $client2 = RC::getConnection(true); - $options = array('watch' => 'foo', 'cas' => true, 'retry' => 1); - $replies = $client->multiExec($options, function($tx) - use ($client2, &$hijack) { - - $foo = $tx->get('foo'); - $tx->multi(); - $tx->set('foobar', $foo); - $tx->discard(); - if ($hijack) { - $hijack = false; - $client2->set('foo', 'hijacked!'); - } - $tx->mget('foo', 'foobar'); - }); - $this->assertInternalType('array', $replies); - $this->assertEquals(array(array('hijacked!', null)), $replies); - } -} diff --git a/test/PredisShared.php b/test/PredisShared.php deleted file mode 100644 index 1647a788..00000000 --- a/test/PredisShared.php +++ /dev/null @@ -1,283 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (!file_exists(__DIR__.'/enable.tests')) { - exit( - "Please create an empty file named 'enable.tests' inside the test directory ". - "in order to proceed.\n\n*** DO NOT *** run this test suite against servers in ". - "a production environment or containing data you are interested in!\n" - ); -} - -if (!function_exists('array_union')) { - function array_union(Array $a, Array $b) - { - return array_merge($a, array_diff($b, $a)); - } -} - -class RC -{ - const SERVER_VERSION = TEST_SERVER_VERSION; - const SERVER_HOST = TEST_SERVER_HOST; - const SERVER_PORT = TEST_SERVER_PORT; - const DEFAULT_DATABASE = TEST_SERVER_DBNUM; - - const WIPE_OUT = 1; - const EXCEPTION_WRONG_TYPE = 'ERR Operation against a key holding the wrong kind of value'; - const EXCEPTION_NO_SUCH_KEY = 'ERR no such key'; - const EXCEPTION_OUT_OF_RANGE = 'ERR index out of range'; - const EXCEPTION_OFFSET_RANGE = 'ERR offset is out of range'; - const EXCEPTION_INVALID_DB_IDX = 'ERR invalid DB index'; - const EXCEPTION_VALUE_NOT_INT = 'ERR value is not an integer'; - const EXCEPTION_EXEC_NO_MULTI = 'ERR EXEC without MULTI'; - const EXCEPTION_SETEX_TTL = 'ERR invalid expire time in SETEX'; - const EXCEPTION_HASH_VALNOTINT = 'ERR hash value is not an integer'; - const EXCEPTION_BIT_VALUE = 'ERR bit is not an integer or out of range'; - const EXCEPTION_BIT_OFFSET = 'ERR bit offset is not an integer or out of range'; - - private static $connection; - - public static function getConnectionArguments(Array $additional = array()) - { - return array_merge(array('host' => RC::SERVER_HOST, 'port' => RC::SERVER_PORT), $additional); - } - - public static function getConnectionParameters(Array $additional = array()) - { - return new Predis\ConnectionParameters(self::getConnectionArguments($additional)); - } - - public static function createConnection(Array $additional = array()) - { - $serverProfile = Predis\Profiles\ServerProfile::get(self::SERVER_VERSION); - - $connection = new Predis\Client(RC::getConnectionArguments($additional), $serverProfile); - $connection->connect(); - $connection->select(RC::DEFAULT_DATABASE); - - return $connection; - } - - public static function getConnection($new = false) - { - if ($new == true) { - return self::createConnection(); - } - - if (self::$connection === null || !self::$connection->isConnected()) { - self::$connection = self::createConnection(); - } - - return self::$connection; - } - - public static function resetConnection() - { - if (self::$connection !== null && self::$connection->isConnected()) { - self::$connection->disconnect(); - self::$connection = self::createConnection(); - } - } - - public static function helperForBlockingPops($op) - { - // TODO: I admit that this helper is kinda lame and it does not run - // in a separate process to properly test BLPOP/BRPOP - $redisUri = sprintf('tcp://%s:%d/?database=%d', RC::SERVER_HOST, RC::SERVER_PORT, RC::DEFAULT_DATABASE); - $handle = popen('php', 'w'); - - fwrite($handle, "rpush('{$op}1', 'a'); - \$redis->rpush('{$op}2', 'b'); - \$redis->rpush('{$op}3', 'c'); - \$redis->rpush('{$op}1', 'd'); - ?>"); - - pclose($handle); - } - - public static function getArrayOfNumbers() - { - return array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); - } - - public static function getKeyValueArray() - { - return array( - 'foo' => 'bar', - 'hoge' => 'piyo', - 'foofoo' => 'barbar', - ); - } - - public static function getNamespacedKeyValueArray() - { - return array( - 'metavar:foo' => 'bar', - 'metavar:hoge' => 'piyo', - 'metavar:foofoo' => 'barbar', - ); - } - - public static function getZSetArray() - { - return array('a' => -10, 'b' => 0, 'c' => 10, 'd' => 20, 'e' => 20, 'f' => 30); - } - - public static function sameValuesInArrays($arrayA, $arrayB) - { - if (count($arrayA) != count($arrayB)) { - return false; - } - - return count(array_diff($arrayA, $arrayB)) == 0; - } - - public static function testForServerException($testcaseInstance, $expectedMessage, $wrapFunction) - { - $thrownException = null; - - try { - $wrapFunction($testcaseInstance); - } - catch (Predis\ServerException $exception) { - $thrownException = $exception; - } - - $testcaseInstance->assertInstanceOf('Predis\ServerException', $thrownException); - - if (isset($expectedMessage)) { - $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage()); - } - } - - public static function testForClientException($testcaseInstance, $expectedMessage, $wrapFunction) - { - $thrownException = null; - - try { - $wrapFunction($testcaseInstance); - } - catch (Predis\ClientException $exception) { - $thrownException = $exception; - } - - $testcaseInstance->assertInstanceOf('Predis\ClientException', $thrownException); - - if (isset($expectedMessage)) { - $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage()); - } - } - - public static function testForCommunicationException($testcaseInstance, $expectedMessage, $wrapFunction) - { - $thrownException = null; - - try { - $wrapFunction($testcaseInstance); - } - catch (Predis\CommunicationException $exception) { - $thrownException = $exception; - } - - $testcaseInstance->assertInstanceOf('Predis\CommunicationException', $thrownException); - - if (isset($expectedMessage)) { - $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage()); - } - } - - public static function testForAbortedMultiExecException($testcaseInstance, $wrapFunction) - { - $thrownException = null; - - try { - $wrapFunction($testcaseInstance); - } - catch (Predis\Transaction\AbortedMultiExecException $exception) { - $thrownException = $exception; - } - - $testcaseInstance->assertInstanceOf('Predis\Transaction\AbortedMultiExecException', $thrownException); - } - - public static function pushTailAndReturn(Predis\Client $client, $keyName, Array $values, $wipeOut = 0) - { - if ($wipeOut == true) { - $client->del($keyName); - } - - foreach ($values as $value) { - $client->rpush($keyName, $value); - } - - return $values; - } - - public static function setAddAndReturn(Predis\Client $client, $keyName, Array $values, $wipeOut = 0) - { - if ($wipeOut == true) { - $client->del($keyName); - } - - foreach ($values as $value) { - $client->sadd($keyName, $value); - } - - return $values; - } - - public static function zsetAddAndReturn(Predis\Client $client, $keyName, Array $values, $wipeOut = 0) - { - // $values: array(SCORE => VALUE, ...); - if ($wipeOut == true) { - $client->del($keyName); - } - - foreach ($values as $value => $score) { - $client->zadd($keyName, $score, $value); - } - - return $values; - } - - public static function getConnectionParametersArgumentsArray() - { - return array( - 'host' => '10.0.0.1', - 'port' => 6380, - 'connection_timeout' => 10, - 'read_write_timeout' => 30, - 'database' => 5, - 'password' => 'dbpassword', - 'alias' => 'connection_alias', - ); - } - - public static function getConnectionParametersArgumentsString($arguments = null) - { - // TODO: must be improved - $args = $arguments ?: RC::getConnectionParametersArgumentsArray(); - $paramsString = "tcp://{$args['host']}:{$args['port']}/?"; - - unset($args['host']); - unset($args['port']); - - foreach($args as $k => $v) { - $paramsString .= "$k=$v&"; - } - - return $paramsString; - } -} diff --git a/test/RedisCommandsTest.php b/test/RedisCommandsTest.php deleted file mode 100644 index b4c24f94..00000000 --- a/test/RedisCommandsTest.php +++ /dev/null @@ -1,2181 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class RedisCommandTestSuite extends PHPUnit_Framework_TestCase -{ - public $redis; - - // TODO: instead of an boolean assertion against the return value - // of RC::sameValuesInArrays, we should extend PHPUnit with - // a new assertion, e.g. $this->assertSameValues(); - // TODO: an option to skip certain tests such as testflushdbs - // should be provided. - // TODO: missing test with float values for a few commands - - protected function setUp() - { - $this->redis = RC::getConnection(); - $this->redis->flushdb(); - } - - protected function tearDown() - { - } - - protected function onNotSuccessfulTest(Exception $exception) - { - // drops and reconnect to a redis server on uncaught exceptions - RC::resetConnection(); - - parent::onNotSuccessfulTest($exception); - } - - /* miscellaneous commands */ - - function testPing() - { - $this->assertTrue($this->redis->ping()); - } - - function testEcho() - { - $string = 'This is an echo test!'; - $this->assertEquals($string, $this->redis->echo($string)); - } - - function testQuit() - { - $this->redis->quit(); - $this->assertFalse($this->redis->isConnected()); - } - - function testMultiExec() - { - // NOTE: due to a limitation in the current implementation of Predis\Client, - // the replies returned by Predis\Commands\Exec are not parsed by their - // respective Predis\Commands\Command::parseResponse methods. If you - // need that kind of behaviour, you should use an instance of - // Predis\MultiExecBlock. - - $this->assertTrue($this->redis->multi()); - $this->assertInstanceOf('Predis\ResponseQueued', $this->redis->ping()); - $this->assertInstanceOf('Predis\ResponseQueued', $this->redis->echo('hello')); - $this->assertInstanceOf('Predis\ResponseQueued', $this->redis->echo('redis')); - $this->assertEquals(array('PONG', 'hello', 'redis'), $this->redis->exec()); - - $this->assertTrue($this->redis->multi()); - $this->assertEquals(array(), $this->redis->exec()); - - // should throw an exception when trying to EXEC without having previously issued MULTI - RC::testForServerException($this, RC::EXCEPTION_EXEC_NO_MULTI, function($test) { - $test->redis->exec(); - }); - } - - function testDiscard() - { - $this->assertTrue($this->redis->multi()); - $this->assertInstanceOf('Predis\ResponseQueued', $this->redis->set('foo', 'bar')); - $this->assertInstanceOf('Predis\ResponseQueued', $this->redis->set('hoge', 'piyo')); - $this->assertEquals(true, $this->redis->discard()); - - // should throw an exception when trying to EXEC after a DISCARD - RC::testForServerException($this, RC::EXCEPTION_EXEC_NO_MULTI, function($test) { - $test->redis->exec(); - }); - - $this->assertFalse($this->redis->exists('foo')); - $this->assertFalse($this->redis->exists('hoge')); - } - - /* commands operating on string values */ - - function testSet() - { - $this->assertTrue($this->redis->set('foo', 'bar')); - $this->assertEquals('bar', $this->redis->get('foo')); - } - - function testGet() - { - $this->redis->set('foo', 'bar'); - $this->assertEquals('bar', $this->redis->get('foo')); - - $this->assertTrue($this->redis->set('foo', '')); - $this->assertEquals('', $this->redis->get('foo')); - - $this->assertNull($this->redis->get('fooDoesNotExist')); - - // should throw an exception when trying to do a GET on non-string types - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->get('metavars'); - }); - } - - function testExists() - { - $this->redis->set('foo', 'bar'); - - $this->assertTrue($this->redis->exists('foo')); - $this->assertFalse($this->redis->exists('key_does_not_exist')); - } - - function testSetPreserve() - { - $multi = RC::getKeyValueArray(); - - $this->assertTrue($this->redis->setnx('foo', 'bar')); - $this->assertFalse($this->redis->setnx('foo', 'rab')); - $this->assertEquals('bar', $this->redis->get('foo')); - } - - function testMultipleSetAndGet() - { - $multi = RC::getKeyValueArray(); - - // key=>value pairs via array instance - $this->assertTrue($this->redis->mset($multi)); - $multiRet = $this->redis->mget(array_keys($multi)); - $this->assertEquals($multi, array_combine(array_keys($multi), array_values($multiRet))); - - // key=>value pairs via function arguments - $this->assertTrue($this->redis->mset('a', 1, 'b', 2, 'c', 3)); - $this->assertEquals(array(1, 2, 3), $this->redis->mget('a', 'b', 'c')); - } - - function testSetMultiplePreserve() - { - $multi = RC::getKeyValueArray(); - $newpair = array('hogehoge' => 'piyopiyo'); - $hijacked = array('foo' => 'baz', 'hoge' => 'fuga'); - - // successful set - $expectedResult = array_merge($multi, $newpair); - $this->redis->mset($multi); - $this->assertTrue($this->redis->msetnx($newpair)); - $this->assertEquals( - array_values($expectedResult), - $this->redis->mget(array_keys($expectedResult)) - ); - - $this->redis->flushdb(); - - // unsuccessful set - $expectedResult = array_merge($multi, array('hogehoge' => null)); - $this->redis->mset($multi); - $this->assertFalse($this->redis->msetnx(array_merge($newpair, $hijacked))); - $this->assertEquals( - array_values($expectedResult), - $this->redis->mget(array_keys($expectedResult)) - ); - } - - function testGetSet() - { - $this->assertNull($this->redis->getset('foo', 'bar')); - $this->assertEquals('bar', $this->redis->getset('foo', 'barbar')); - $this->assertEquals('barbar', $this->redis->getset('foo', 'baz')); - } - - function testIncrementAndIncrementBy() - { - // test subsequent increment commands - $this->assertEquals(1, $this->redis->incr('foo')); - $this->assertEquals(2, $this->redis->incr('foo')); - - // test subsequent incrementBy commands - $this->assertEquals(22, $this->redis->incrby('foo', 20)); - $this->assertEquals(10, $this->redis->incrby('foo', -12)); - $this->assertEquals(-100, $this->redis->incrby('foo', -110)); - } - - function testDecrementAndDecrementBy() - { - // test subsequent decrement commands - $this->assertEquals(-1, $this->redis->decr('foo')); - $this->assertEquals(-2, $this->redis->decr('foo')); - - // test subsequent decrementBy commands - $this->assertEquals(-22, $this->redis->decrby('foo', 20)); - $this->assertEquals(-10, $this->redis->decrby('foo', -12)); - $this->assertEquals(100, $this->redis->decrby('foo', -110)); - } - - function testDelete() - { - $this->redis->set('foo', 'bar'); - $this->assertEquals(1, $this->redis->del('foo')); - $this->assertFalse($this->redis->exists('foo')); - $this->assertEquals(0, $this->redis->del('foo')); - } - - function testType() - { - $this->assertEquals('none', $this->redis->type('fooDoesNotExist')); - - $this->redis->set('fooString', 'bar'); - $this->assertEquals('string', $this->redis->type('fooString')); - - $this->redis->rpush('fooList', 'bar'); - $this->assertEquals('list', $this->redis->type('fooList')); - - $this->redis->sadd('fooSet', 'bar'); - $this->assertEquals('set', $this->redis->type('fooSet')); - - $this->redis->zadd('fooZSet', 0, 'bar'); - $this->assertEquals('zset', $this->redis->type('fooZSet')); - - $this->redis->hset('fooHash', 'value', 'bar'); - $this->assertEquals('hash', $this->redis->type('fooHash')); - } - - function testAppend() - { - $this->redis->set('foo', 'bar'); - $this->assertEquals(5, $this->redis->append('foo', '__')); - $this->assertEquals(8, $this->redis->append('foo', 'bar')); - $this->assertEquals('bar__bar', $this->redis->get('foo')); - - $this->assertEquals(4, $this->redis->append('hoge', 'piyo')); - $this->assertEquals('piyo', $this->redis->get('hoge')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->append('metavars', 'bar'); - }); - } - - function testSetRange() - { - $this->assertEquals(6, $this->redis->setrange('var', 0, 'foobar')); - $this->assertEquals('foobar', $this->redis->get('var')); - $this->assertEquals(6, $this->redis->setrange('var', 3, 'foo')); - $this->assertEquals('foofoo', $this->redis->get('var')); - $this->assertEquals(16, $this->redis->setrange('var', 10, 'barbar')); - $this->assertEquals("foofoo\x00\x00\x00\x00barbar", $this->redis->get('var')); - - $this->assertEquals(4, $this->redis->setrange('binary', 0, pack('l', -2147483648))); - list($unpacked) = array_values(unpack('l', $this->redis->get('binary'))); - $this->assertEquals(-2147483648, $unpacked); - - RC::testForServerException($this, RC::EXCEPTION_OFFSET_RANGE, function($test) { - $test->redis->setrange('var', -1, 'bogus'); - }); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->setrange('metavars', 0, 'hoge'); - }); - } - - function testSubstr() - { - $this->redis->set('var', 'foobar'); - $this->assertEquals('foo', $this->redis->substr('var', 0, 2)); - $this->assertEquals('bar', $this->redis->substr('var', 3, 5)); - $this->assertEquals('bar', $this->redis->substr('var', -3, -1)); - - $this->assertEquals('', $this->redis->substr('var', 5, 0)); - - $this->redis->set('numeric', 123456789); - $this->assertEquals(12345, $this->redis->substr('numeric', 0, 4)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->substr('metavars', 0, 3); - }); - } - - function testStrlen() - { - $this->redis->set('var', 'foobar'); - $this->assertEquals(6, $this->redis->strlen('var')); - $this->assertEquals(9, $this->redis->append('var', '___')); - $this->assertEquals(9, $this->redis->strlen('var')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->strlen('metavars'); - }); - } - - function testSetBit() - { - $this->assertEquals(0, $this->redis->setbit('binary', 31, 1)); - $this->assertEquals(0, $this->redis->setbit('binary', 0, 1)); - $this->assertEquals(4, $this->redis->strlen('binary')); - $this->assertEquals("\x80\x00\00\x01", $this->redis->get('binary')); - - $this->assertEquals(1, $this->redis->setbit('binary', 0, 0)); - $this->assertEquals(0, $this->redis->setbit('binary', 0, 0)); - $this->assertEquals("\x00\x00\00\x01", $this->redis->get('binary')); - - RC::testForServerException($this, RC::EXCEPTION_BIT_OFFSET, function($test) { - $test->redis->setbit('binary', -1, 1); - }); - - RC::testForServerException($this, RC::EXCEPTION_BIT_OFFSET, function($test) { - $test->redis->setbit('binary', 'invalid', 1); - }); - - RC::testForServerException($this, RC::EXCEPTION_BIT_VALUE, function($test) { - $test->redis->setbit('binary', 15, 255); - }); - - RC::testForServerException($this, RC::EXCEPTION_BIT_VALUE, function($test) { - $test->redis->setbit('binary', 15, 'invalid'); - }); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->setbit('metavars', 0, 1); - }); - } - - function testGetBit() - { - $this->redis->set('binary', "\x80\x00\00\x01"); - - $this->assertEquals(1, $this->redis->getbit('binary', 0)); - $this->assertEquals(0, $this->redis->getbit('binary', 15)); - $this->assertEquals(1, $this->redis->getbit('binary', 31)); - $this->assertEquals(0, $this->redis->getbit('binary', 63)); - - RC::testForServerException($this, RC::EXCEPTION_BIT_OFFSET, function($test) { - $test->redis->getbit('binary', -1); - }); - - RC::testForServerException($this, RC::EXCEPTION_BIT_OFFSET, function($test) { - $test->redis->getbit('binary', 'invalid'); - }); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->getbit('metavars', 0); - }); - } - - /* commands operating on the key space */ - - function testKeys() - { - $keyValsNs = RC::getNamespacedKeyValueArray(); - $keyValsOthers = array('aaa' => 1, 'aba' => 2, 'aca' => 3); - $allKeyVals = array_merge($keyValsNs, $keyValsOthers); - - $this->redis->mset($allKeyVals); - - $this->assertEquals(array(), $this->redis->keys('nokeys:*')); - - $keysFromRedis = $this->redis->keys('metavar:*'); - $this->assertEquals(array(), array_diff(array_keys($keyValsNs), $keysFromRedis)); - - $keysFromRedis = $this->redis->keys('*'); - $this->assertEquals(array(), array_diff(array_keys($allKeyVals), $keysFromRedis)); - - $keysFromRedis = $this->redis->keys('a?a'); - $this->assertEquals(array(), array_diff(array_keys($keyValsOthers), $keysFromRedis)); - } - - function testRandomKey() - { - $keyvals = RC::getKeyValueArray(); - - $this->assertNull($this->redis->randomkey()); - - $this->redis->mset($keyvals); - $this->assertTrue(in_array($this->redis->randomkey(), array_keys($keyvals))); - } - - function testRename() - { - $this->redis->mset(array('foo' => 'bar', 'foofoo' => 'barbar')); - - // rename existing keys - $this->assertTrue($this->redis->rename('foo', 'foofoo')); - $this->assertFalse($this->redis->exists('foo')); - $this->assertEquals('bar', $this->redis->get('foofoo')); - - // should throw an excepion then trying to rename non-existing keys - RC::testForServerException($this, RC::EXCEPTION_NO_SUCH_KEY, function($test) { - $test->redis->rename('hoge', 'hogehoge'); - }); - } - - function testRenamePreserve() - { - $this->redis->mset(array('foo' => 'bar', 'hoge' => 'piyo', 'hogehoge' => 'piyopiyo')); - - $this->assertTrue($this->redis->renamenx('foo', 'foofoo')); - $this->assertFalse($this->redis->exists('foo')); - $this->assertEquals('bar', $this->redis->get('foofoo')); - - $this->assertFalse($this->redis->renamenx('hoge', 'hogehoge')); - $this->assertTrue($this->redis->exists('hoge')); - - // should throw an excepion then trying to rename non-existing keys - RC::testForServerException($this, RC::EXCEPTION_NO_SUCH_KEY, function($test) { - $test->redis->renamenx('fuga', 'baz'); - }); - } - - function testExpirationAndTTL() - { - $this->redis->set('foo', 'bar'); - - // check for key expiration - $this->assertTrue($this->redis->expire('foo', 1)); - $this->assertEquals(1, $this->redis->ttl('foo')); - $this->assertTrue($this->redis->exists('foo')); - sleep(2); - $this->assertFalse($this->redis->exists('foo')); - $this->assertEquals(-1, $this->redis->ttl('foo')); - - // check for consistent TTL values - $this->redis->set('foo', 'bar'); - $this->assertTrue($this->redis->expire('foo', 100)); - sleep(3); - $this->assertEquals(97, $this->redis->ttl('foo')); - - // delete key on negative TTL - $this->redis->set('foo', 'bar'); - $this->assertTrue($this->redis->expire('foo', -100)); - $this->assertFalse($this->redis->exists('foo')); - $this->assertEquals(-1, $this->redis->ttl('foo')); - } - - function testPersist() - { - $this->redis->set('foo', 'bar'); - - $this->assertTrue($this->redis->expire('foo', 1)); - $this->assertEquals(1, $this->redis->ttl('foo')); - $this->assertTrue($this->redis->persist('foo')); - $this->assertEquals(-1, $this->redis->ttl('foo')); - - $this->assertFalse($this->redis->persist('foo')); - $this->assertFalse($this->redis->persist('foobar')); - } - - function testSetExpire() - { - $this->assertTrue($this->redis->setex('foo', 10, 'bar')); - $this->assertTrue($this->redis->exists('foo')); - $this->assertEquals(10, $this->redis->ttl('foo')); - - $this->assertTrue($this->redis->setex('hoge', 1, 'piyo')); - sleep(2); - $this->assertFalse($this->redis->exists('hoge')); - - // TODO: do not check the error message RC::EXCEPTION_VALUE_NOT_INT for now - RC::testForServerException($this, null, function($test) { - $test->redis->setex('hoge', 2.5, 'piyo'); - }); - RC::testForServerException($this, RC::EXCEPTION_SETEX_TTL, function($test) { - $test->redis->setex('hoge', 0, 'piyo'); - }); - RC::testForServerException($this, RC::EXCEPTION_SETEX_TTL, function($test) { - $test->redis->setex('hoge', -10, 'piyo'); - }); - } - - function testDatabaseSize() - { - // TODO: is this really OK? - $this->assertEquals(0, $this->redis->dbsize()); - $this->redis->mset(RC::getKeyValueArray()); - $this->assertGreaterThan(0, $this->redis->dbsize()); - } - - /* commands operating on lists */ - - function testPushTail() - { - // NOTE: List push operations return the list length since Redis commit 520b5a3 - $this->assertEquals(1, $this->redis->rpush('metavars', 'foo')); - $this->assertTrue($this->redis->exists('metavars')); - $this->assertEquals(2, $this->redis->rpush('metavars', 'hoge')); - - // should throw an exception when trying to do a RPUSH on non-list types - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->rpush('foo', 'bar'); - }); - } - - function testPushTailX() - { - $this->assertEquals(0, $this->redis->rpushx('numbers', 1)); - $this->assertEquals(1, $this->redis->rpush('numbers', 2)); - $this->assertEquals(2, $this->redis->rpushx('numbers', 3)); - - $this->assertEquals(2, $this->redis->llen('numbers')); - $this->assertEquals(array(2, 3), $this->redis->lrange('numbers', 0, -1)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->rpushx('foo', 'bar'); - }); - } - - function testPushHead() - { - // NOTE: List push operations return the list length since Redis commit 520b5a3 - $this->assertEquals(1, $this->redis->lpush('metavars', 'foo')); - $this->assertTrue($this->redis->exists('metavars')); - $this->assertEquals(2, $this->redis->lpush('metavars', 'hoge')); - - // should throw an exception when trying to do a LPUSH on non-list types - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->lpush('foo', 'bar'); - }); - } - - function testPushHeadX() - { - $this->assertEquals(0, $this->redis->lpushx('numbers', 1)); - $this->assertEquals(1, $this->redis->lpush('numbers', 2)); - $this->assertEquals(2, $this->redis->lpushx('numbers', 3)); - - $this->assertEquals(2, $this->redis->llen('numbers')); - $this->assertEquals(array(3, 2), $this->redis->lrange('numbers', 0, -1)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->lpushx('foo', 'bar'); - }); - } - - function testListLength() - { - $this->assertEquals(1, $this->redis->rpush('metavars', 'foo')); - $this->assertEquals(2, $this->redis->rpush('metavars', 'hoge')); - $this->assertEquals(2, $this->redis->llen('metavars')); - - $this->assertEquals(0, $this->redis->llen('doesnotexist')); - - // should throw an exception when trying to do a LLEN on non-list types - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->llen('foo'); - }); - } - - function testListRange() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers()); - - $this->assertEquals( - array_slice($numbers, 0, 4), - $this->redis->lrange('numbers', 0, 3) - ); - $this->assertEquals( - array_slice($numbers, 4, 5), - $this->redis->lrange('numbers', 4, 8) - ); - $this->assertEquals( - array_slice($numbers, 0, 1), - $this->redis->lrange('numbers', 0, 0) - ); - $this->assertEquals( - array(), - $this->redis->lrange('numbers', 1, 0) - ); - $this->assertEquals( - $numbers, - $this->redis->lrange('numbers', 0, -1) - ); - $this->assertEquals( - array(5), - $this->redis->lrange('numbers', 5, -5) - ); - $this->assertEquals( - array(), - $this->redis->lrange('numbers', 7, -5) - ); - $this->assertEquals( - array_slice($numbers, -5, -1), - $this->redis->lrange('numbers', -5, -2) - ); - $this->assertEquals( - $numbers, - $this->redis->lrange('numbers', -100, 100) - ); - - $this->assertEquals( - array(), - $this->redis->lrange('keyDoesNotExist', 0, 1) - ); - - // should throw an exception when trying to do a LRANGE on non-list types - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->lrange('foo', 0, -1); - }); - } - - function testListTrim() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers()); - $this->assertTrue($this->redis->ltrim('numbers', 0, 2)); - $this->assertEquals( - array_slice($numbers, 0, 3), - $this->redis->lrange('numbers', 0, -1) - ); - - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers(), RC::WIPE_OUT); - $this->assertTrue($this->redis->ltrim('numbers', 5, 9)); - $this->assertEquals( - array_slice($numbers, 5, 5), - $this->redis->lrange('numbers', 0, -1) - ); - - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers(), RC::WIPE_OUT); - $this->assertTrue($this->redis->ltrim('numbers', 0, -6)); - $this->assertEquals( - array_slice($numbers, 0, -5), - $this->redis->lrange('numbers', 0, -1) - ); - - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers(), RC::WIPE_OUT); - $this->assertTrue($this->redis->ltrim('numbers', -5, -3)); - $this->assertEquals( - array_slice($numbers, 5, 3), - $this->redis->lrange('numbers', 0, -1) - ); - - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers(), RC::WIPE_OUT); - $this->assertTrue($this->redis->ltrim('numbers', -100, 100)); - $this->assertEquals( - $numbers, - $this->redis->lrange('numbers', 0, -1) - ); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->ltrim('foo', 0, 1); - }); - } - - function testListIndex() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers()); - - $this->assertEquals(0, $this->redis->lindex('numbers', 0)); - $this->assertEquals(5, $this->redis->lindex('numbers', 5)); - $this->assertEquals(9, $this->redis->lindex('numbers', 9)); - $this->assertNull($this->redis->lindex('numbers', 100)); - - $this->assertEquals(0, $this->redis->lindex('numbers', -0)); - $this->assertEquals(9, $this->redis->lindex('numbers', -1)); - $this->assertEquals(7, $this->redis->lindex('numbers', -3)); - $this->assertNull($this->redis->lindex('numbers', -100)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->lindex('foo', 0); - }); - } - - function testListSet() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers()); - - $this->assertTrue($this->redis->lset('numbers', 5, -5)); - $this->assertEquals(-5, $this->redis->lindex('numbers', 5)); - - RC::testForServerException($this, RC::EXCEPTION_OUT_OF_RANGE, function($test) { - $test->redis->lset('numbers', 99, 99); - }); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->lset('foo', 0, 0); - }); - } - - function testListRemove() - { - $mixed = array(0, '_', 2, '_', 4, '_', 6, '_'); - - RC::pushTailAndReturn($this->redis, 'mixed', $mixed); - $this->assertEquals(2, $this->redis->lrem('mixed', 2, '_')); - $this->assertEquals(array(0, 2, 4, '_', 6, '_'), $this->redis->lrange('mixed', 0, -1)); - - RC::pushTailAndReturn($this->redis, 'mixed', $mixed, RC::WIPE_OUT); - $this->assertEquals(4, $this->redis->lrem('mixed', 0, '_')); - $this->assertEquals(array(0, 2, 4, 6), $this->redis->lrange('mixed', 0, -1)); - - RC::pushTailAndReturn($this->redis, 'mixed', $mixed, RC::WIPE_OUT); - $this->assertEquals(2, $this->redis->lrem('mixed', -2, '_')); - $this->assertEquals(array(0, '_', 2, '_', 4, 6), $this->redis->lrange('mixed', 0, -1)); - - RC::pushTailAndReturn($this->redis, 'mixed', $mixed, RC::WIPE_OUT); - $this->assertEquals(0, $this->redis->lrem('mixed', 2, '|')); - $this->assertEquals($mixed, $this->redis->lrange('mixed', 0, -1)); - - $this->assertEquals(0, $this->redis->lrem('listDoesNotExist', 2, '_')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->lrem('foo', 0, 0); - }); - } - - function testListPopFirst() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', array(0, 1, 2, 3, 4)); - - $this->assertEquals(0, $this->redis->lpop('numbers')); - $this->assertEquals(1, $this->redis->lpop('numbers')); - $this->assertEquals(2, $this->redis->lpop('numbers')); - - $this->assertEquals(array(3, 4), $this->redis->lrange('numbers', 0, -1)); - - $this->redis->lpop('numbers'); - $this->redis->lpop('numbers'); - $this->assertNull($this->redis->lpop('numbers')); - - $this->assertNull($this->redis->lpop('numbers')); - - $this->assertNull($this->redis->lpop('listDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->lpop('foo'); - }); - } - - function testListPopLast() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', array(0, 1, 2, 3, 4)); - - $this->assertEquals(4, $this->redis->rpop('numbers')); - $this->assertEquals(3, $this->redis->rpop('numbers')); - $this->assertEquals(2, $this->redis->rpop('numbers')); - - $this->assertEquals(array(0, 1), $this->redis->lrange('numbers', 0, -1)); - - $this->redis->rpop('numbers'); - $this->redis->rpop('numbers'); - $this->assertNull($this->redis->rpop('numbers')); - - $this->assertNull($this->redis->rpop('numbers')); - - $this->assertNull($this->redis->rpop('listDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->rpop('foo'); - }); - } - - function testListPopLastPushHead() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', array(0, 1, 2)); - $this->assertEquals(0, $this->redis->llen('temporary')); - $this->assertEquals(2, $this->redis->rpoplpush('numbers', 'temporary')); - $this->assertEquals(1, $this->redis->rpoplpush('numbers', 'temporary')); - $this->assertEquals(0, $this->redis->rpoplpush('numbers', 'temporary')); - $this->assertEquals(0, $this->redis->llen('numbers')); - $this->assertEquals(3, $this->redis->llen('temporary')); - $this->assertEquals(array(), $this->redis->lrange('numbers', 0, -1)); - $this->assertEquals($numbers, $this->redis->lrange('temporary', 0, -1)); - - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', array(0, 1, 2)); - $this->redis->rpoplpush('numbers', 'numbers'); - $this->redis->rpoplpush('numbers', 'numbers'); - $this->redis->rpoplpush('numbers', 'numbers'); - $this->assertEquals($numbers, $this->redis->lrange('numbers', 0, -1)); - - $this->assertNull($this->redis->rpoplpush('listDoesNotExist1', 'listDoesNotExist2')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->rpoplpush('foo', 'hoge'); - }); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->rpoplpush('temporary', 'foo'); - }); - } - - function testListBlockingPopFirst() - { - // TODO: this test does not cover all the aspects of BLPOP/BRPOP as it - // does not run with a concurrent client pushing items on lists. - RC::helperForBlockingPops('blpop'); - - // BLPOP on one key - $start = time(); - $item = $this->redis->blpop('blpop3', 5); - $this->assertEquals((float)(time() - $start), 0, '', 1); - $this->assertEquals($item, array('blpop3', 'c')); - - // BLPOP on more than one key - $poppedItems = array(); - while ($item = $this->redis->blpop('blpop1', 'blpop2', 1)) { - $poppedItems[] = $item; - } - $this->assertEquals( - array(array('blpop1', 'a'), array('blpop1', 'd'), array('blpop2', 'b')), - $poppedItems - ); - - // check if BLPOP timeouts as expected on empty lists - $start = time(); - $this->redis->blpop('blpop4', 2); - $this->assertEquals((float)(time() - $start), 2, '', 1); - } - - function testListBlockingPopLast() - { - // TODO: this test does not cover all the aspects of BLPOP/BRPOP as it - // does not run with a concurrent client pushing items on lists. - RC::helperForBlockingPops('brpop'); - - // BRPOP on one key - $start = time(); - $item = $this->redis->brpop('brpop3', 5); - $this->assertEquals((float)(time() - $start), 0, '', 1); - $this->assertEquals($item, array('brpop3', 'c')); - - // BRPOP on more than one key - $poppedItems = array(); - while ($item = $this->redis->brpop('brpop1', 'brpop2', 1)) { - $poppedItems[] = $item; - } - $this->assertEquals( - array(array('brpop1', 'd'), array('brpop1', 'a'), array('brpop2', 'b')), - $poppedItems - ); - - // check if BRPOP timeouts as expected on empty lists - $start = time(); - $this->redis->brpop('brpop4', 2); - $this->assertEquals((float)(time() - $start), 2, '', 1); - } - - function testListBlockingPopLastPushHead() - { - // TODO: this test does not cover all the aspects of BLPOP/BRPOP as it - // does not run with a concurrent client pushing items on lists. - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', array(1, 2, 3)); - $src_count = count($numbers); - $dst_count = 0; - - while ($item = $this->redis->brpoplpush('numbers', 'temporary', 1)) { - $this->assertEquals(--$src_count, $this->redis->llen('numbers')); - $this->assertEquals(++$dst_count, $this->redis->llen('temporary')); - $this->assertEquals(array_pop($numbers), $this->redis->lindex('temporary', 0)); - } - - $start = time(); - $this->assertNull($this->redis->brpoplpush('numbers', 'temporary', 2)); - $this->assertEquals(2, (float)(time() - $start), '', 1); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->del('numbers'); - $test->redis->del('temporary'); - $test->redis->set('numbers', 'foobar'); - $test->redis->brpoplpush('numbers', 'temporary', 1); - }); - } - - function testListInsert() - { - $numbers = RC::pushTailAndReturn($this->redis, 'numbers', RC::getArrayOfNumbers()); - - $this->assertEquals(11, $this->redis->linsert('numbers', 'before', 0, -2)); - $this->assertEquals(12, $this->redis->linsert('numbers', 'after', -2, -1)); - $this->assertEquals(array(-2, -1, 0, 1), $this->redis->lrange('numbers', 0, 3)); - - $this->assertEquals(-1, $this->redis->linsert('numbers', 'after', 100, 200)); - $this->assertEquals(-1, $this->redis->linsert('numbers', 'before', 100, 50)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->linsert('foo', 'before', 0, 0); - }); - } - - /* commands operating on sets */ - - function testSetAdd() - { - $this->assertTrue($this->redis->sadd('set', 0)); - $this->assertTrue($this->redis->sadd('set', 1)); - $this->assertFalse($this->redis->sadd('set', 0)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->sadd('foo', 0); - }); - } - - function testSetRemove() - { - $set = RC::setAddAndReturn($this->redis, 'set', array(0, 1, 2, 3, 4)); - - $this->assertTrue($this->redis->srem('set', 0)); - $this->assertTrue($this->redis->srem('set', 4)); - $this->assertFalse($this->redis->srem('set', 10)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->srem('foo', 0); - }); - } - - function testSetPop() - { - $set = RC::setAddAndReturn($this->redis, 'set', array(0, 1, 2, 3, 4)); - - $this->assertTrue(in_array($this->redis->spop('set'), $set)); - - $this->assertNull($this->redis->spop('setDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->spop('foo'); - }); - } - - function testSetMove() - { - $setA = RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5)); - $setB = RC::setAddAndReturn($this->redis, 'setB', array(5, 6, 7, 8, 9, 10)); - - $this->assertTrue($this->redis->smove('setA', 'setB', 0)); - $this->assertFalse($this->redis->srem('setA', 0)); - $this->assertTrue($this->redis->srem('setB', 0)); - - $this->assertTrue($this->redis->smove('setA', 'setB', 5)); - $this->assertFalse($this->redis->smove('setA', 'setB', 100)); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->smove('foo', 'setB', 5); - }); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->smove('setA', 'foo', 5); - }); - } - - function testSetCardinality() - { - RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5)); - - $this->assertEquals(6, $this->redis->scard('setA')); - - // empty set - $this->redis->sadd('setB', 0); - $this->redis->spop('setB'); - $this->assertEquals(0, $this->redis->scard('setB')); - - // non-existing set - $this->assertEquals(0, $this->redis->scard('setDoesNotExist')); - - // wrong type - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->scard('foo'); - }); - } - - function testSetIsMember() - { - RC::setAddAndReturn($this->redis, 'set', array(0, 1, 2, 3, 4, 5)); - - $this->assertTrue($this->redis->sismember('set', 3)); - $this->assertFalse($this->redis->sismember('set', 100)); - - $this->assertFalse($this->redis->sismember('setDoesNotExist', 0)); - - // wrong type - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->sismember('foo', 0); - }); - } - - function testSetMembers() - { - $set = RC::setAddAndReturn($this->redis, 'set', array(0, 1, 2, 3, 4, 5, 6)); - - $this->assertTrue(RC::sameValuesInArrays($set, $this->redis->smembers('set'))); - - $this->assertEquals(array(), $this->redis->smembers('setDoesNotExist')); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->smembers('foo'); - }); - } - - function testSetIntersection() - { - $setA = RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5, 6)); - $setB = RC::setAddAndReturn($this->redis, 'setB', array(1, 3, 4, 6, 9, 10)); - - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->sinter('setA') - )); - - $this->assertTrue(RC::sameValuesInArrays( - array_intersect($setA, $setB), - $this->redis->sinter('setA', 'setB') - )); - - $this->assertEquals(array(), $this->redis->sinter('setA', 'setDoesNotExist')); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sinter('foo'); - }); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sinter('setA', 'foo'); - }); - } - - function testSetIntersectionStore() - { - $setA = RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5, 6)); - $setB = RC::setAddAndReturn($this->redis, 'setB', array(1, 3, 4, 6, 9, 10)); - - $this->assertEquals(count($setA), $this->redis->sinterstore('setC', 'setA')); - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->smembers('setC') - )); - - $this->redis->del('setC'); - $this->assertEquals(4, $this->redis->sinterstore('setC', 'setA', 'setB')); - $this->assertTrue(RC::sameValuesInArrays( - array(1, 3, 4, 6), - $this->redis->smembers('setC') - )); - - $this->redis->del('setC'); - $this->assertEquals(array(), $this->redis->sinter('setC', 'setDoesNotExist')); - $this->assertFalse($this->redis->exists('setC')); - - // existing keys are replaced by SINTERSTORE - $this->redis->set('foo', 'bar'); - $this->assertEquals(count($setA), $this->redis->sinterstore('foo', 'setA')); - - // accepts an array for the list of source keys - $this->assertEquals(4, $this->redis->sinterstore('setC', array('setA', 'setB'))); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sinterstore('setA', 'foo'); - }); - } - - function testSetUnion() - { - $setA = RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5, 6)); - $setB = RC::setAddAndReturn($this->redis, 'setB', array(1, 3, 4, 6, 9, 10)); - - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->sunion('setA') - )); - - $this->assertTrue(RC::sameValuesInArrays( - array_union($setA, $setB), - $this->redis->sunion('setA', 'setB') - )); - - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->sunion('setA', 'setDoesNotExist') - )); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sunion('foo'); - }); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sunion('setA', 'foo'); - }); - } - - function testSetUnionStore() - { - $setA = RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5, 6)); - $setB = RC::setAddAndReturn($this->redis, 'setB', array(1, 3, 4, 6, 9, 10)); - - $this->assertEquals(count($setA), $this->redis->sunionstore('setC', 'setA')); - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->smembers('setC') - )); - - $this->redis->del('setC'); - $this->assertEquals(9, $this->redis->sunionstore('setC', 'setA', 'setB')); - $this->assertTrue(RC::sameValuesInArrays( - array_union($setA, $setB), - $this->redis->smembers('setC') - )); - - // non-existing keys are considered empty sets - $this->redis->del('setC'); - $this->assertEquals(0, $this->redis->sunionstore('setC', 'setDoesNotExist')); - $this->assertFalse($this->redis->exists('setC')); - $this->assertEquals(0, $this->redis->scard('setC')); - - // existing keys are replaced by SUNIONSTORE - $this->redis->set('foo', 'bar'); - $this->assertEquals(count($setA), $this->redis->sunionstore('foo', 'setA')); - - // accepts an array for the list of source keys - $this->assertEquals(9, $this->redis->sunionstore('setC', array('setA', 'setB'))); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sunionstore('setA', 'foo'); - }); - } - - function testSetDifference() - { - $setA = RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5, 6)); - $setB = RC::setAddAndReturn($this->redis, 'setB', array(1, 3, 4, 6, 9, 10)); - - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->sdiff('setA') - )); - - $this->assertTrue(RC::sameValuesInArrays( - array_diff($setA, $setB), - $this->redis->sdiff('setA', 'setB') - )); - - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->sdiff('setA', 'setDoesNotExist') - )); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sdiff('foo'); - }); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sdiff('setA', 'foo'); - }); - } - - function testSetDifferenceStore() - { - $setA = RC::setAddAndReturn($this->redis, 'setA', array(0, 1, 2, 3, 4, 5, 6)); - $setB = RC::setAddAndReturn($this->redis, 'setB', array(1, 3, 4, 6, 9, 10)); - - $this->assertEquals(count($setA), $this->redis->sdiffstore('setC', 'setA')); - $this->assertTrue(RC::sameValuesInArrays( - $setA, - $this->redis->smembers('setC') - )); - - $this->redis->del('setC'); - $this->assertEquals(3, $this->redis->sdiffstore('setC', 'setA', 'setB')); - $this->assertTrue(RC::sameValuesInArrays( - array_diff($setA, $setB), - $this->redis->smembers('setC') - )); - - // non-existing keys are considered empty sets - $this->redis->del('setC'); - $this->assertEquals(0, $this->redis->sdiffstore('setC', 'setDoesNotExist')); - $this->assertFalse($this->redis->exists('setC')); - $this->assertEquals(0, $this->redis->scard('setC')); - - // existing keys are replaced by SDIFFSTORE - $this->redis->set('foo', 'bar'); - $this->assertEquals(count($setA), $this->redis->sdiffstore('foo', 'setA')); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->sdiffstore('setA', 'foo'); - }); - } - - function testRandomMember() - { - $set = RC::setAddAndReturn($this->redis, 'set', array(0, 1, 2, 3, 4, 5, 6)); - - $this->assertTrue(in_array($this->redis->srandmember('set'), $set)); - - $this->assertNull($this->redis->srandmember('setDoesNotExist')); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->srandmember('foo'); - }); - } - - /* commands operating on sorted sets */ - - function testZsetAdd() - { - $this->assertTrue($this->redis->zadd('zset', 0, 'a')); - $this->assertTrue($this->redis->zadd('zset', 1, 'b')); - - $this->assertTrue($this->redis->zadd('zset', -1, 'c')); - - // TODO: floats? - //$this->assertTrue($this->redis->zadd('zset', -1.0, 'c')); - //$this->assertTrue($this->redis->zadd('zset', -1.0, 'c')); - - $this->assertFalse($this->redis->zadd('zset', 2, 'b')); - $this->assertFalse($this->redis->zadd('zset', -2, 'b')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zadd('foo', 0, 'a'); - }); - } - - function testZsetIncrementBy() - { - $this->assertEquals(1, $this->redis->zincrby('zsetDoesNotExist', 1, 'foo')); - $this->assertEquals('zset', $this->redis->type('zsetDoesNotExist')); - - RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - $this->assertEquals(-5, $this->redis->zincrby('zset', 5, 'a')); - $this->assertEquals(1, $this->redis->zincrby('zset', 1, 'b')); - $this->assertEquals(10, $this->redis->zincrby('zset', 0, 'c')); - $this->assertEquals(0, $this->redis->zincrby('zset', -20, 'd')); - $this->assertEquals(2, $this->redis->zincrby('zset', 2, 'd')); - $this->assertEquals(-10, $this->redis->zincrby('zset', -30, 'e')); - $this->assertEquals(1, $this->redis->zincrby('zset', 1, 'x')); - - // wrong type - $this->redis->set('foo', 'bar'); - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->zincrby('foo', 1, 'a'); - }); - } - - function testZsetRemove() - { - RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertTrue($this->redis->zrem('zset', 'a')); - $this->assertFalse($this->redis->zrem('zset', 'x')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zrem('foo', 'bar'); - }); - } - - function testZsetRange() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals( - array_slice(array_keys($zset), 0, 4), - $this->redis->zrange('zset', 0, 3) - ); - - $this->assertEquals( - array_slice(array_keys($zset), 0, 1), - $this->redis->zrange('zset', 0, 0) - ); - - $this->assertEquals( - array(), - $this->redis->zrange('zset', 1, 0) - ); - - $this->assertEquals( - array_values(array_keys($zset)), - $this->redis->zrange('zset', 0, -1) - ); - - $this->assertEquals( - array_slice(array_keys($zset), 3, 1), - $this->redis->zrange('zset', 3, -3) - ); - - $this->assertEquals( - array(), - $this->redis->zrange('zset', 5, -3) - ); - - $this->assertEquals( - array_slice(array_keys($zset), -5, -1), - $this->redis->zrange('zset', -5, -2) - ); - - $this->assertEquals( - array_values(array_keys($zset)), - $this->redis->zrange('zset', -100, 100) - ); - - $this->assertEquals( - array_values(array_keys($zset)), - $this->redis->zrange('zset', -100, 100) - ); - - $this->assertEquals( - array(array('a', -10), array('b', 0), array('c', 10)), - $this->redis->zrange('zset', 0, 2, 'withscores') - ); - - $this->assertEquals( - array(array('a', -10), array('b', 0), array('c', 10)), - $this->redis->zrange('zset', 0, 2, array('withscores' => true)) - ); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zrange('foo', 0, -1); - }); - } - - function testZsetReverseRange() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals( - array_slice(array_reverse(array_keys($zset)), 0, 4), - $this->redis->zrevrange('zset', 0, 3) - ); - - $this->assertEquals( - array_slice(array_reverse(array_keys($zset)), 0, 1), - $this->redis->zrevrange('zset', 0, 0) - ); - - $this->assertEquals( - array(), - $this->redis->zrevrange('zset', 1, 0) - ); - - $this->assertEquals( - array_values(array_reverse(array_keys($zset))), - $this->redis->zrevrange('zset', 0, -1) - ); - - $this->assertEquals( - array_slice(array_reverse(array_keys($zset)), 3, 1), - $this->redis->zrevrange('zset', 3, -3) - ); - - $this->assertEquals( - array(), - $this->redis->zrevrange('zset', 5, -3) - ); - - $this->assertEquals( - array_slice(array_reverse(array_keys($zset)), -5, -1), - $this->redis->zrevrange('zset', -5, -2) - ); - - $this->assertEquals( - array_values(array_reverse(array_keys($zset))), - $this->redis->zrevrange('zset', -100, 100) - ); - - $this->assertEquals( - array(array('f', 30), array('e', 20), array('d', 20)), - $this->redis->zrevrange('zset', 0, 2, 'withscores') - ); - - $this->assertEquals( - array(array('f', 30), array('e', 20), array('d', 20)), - $this->redis->zrevrange('zset', 0, 2, array('withscores' => true)) - ); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zrevrange('foo', 0, -1); - }); - } - - function testZsetRangeByScore() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals( - array('a'), - $this->redis->zrangebyscore('zset', -10, -10) - ); - - $this->assertEquals( - array('c', 'd', 'e', 'f'), - $this->redis->zrangebyscore('zset', 10, 30) - ); - - $this->assertEquals( - array('d', 'e'), - $this->redis->zrangebyscore('zset', 20, 20) - ); - - $this->assertEquals( - array(), - $this->redis->zrangebyscore('zset', 30, 0) - ); - - $this->assertEquals( - array(array('c', 10), array('d', 20), array('e', 20)), - $this->redis->zrangebyscore('zset', 10, 20, 'withscores') - ); - - $this->assertEquals( - array(array('c', 10), array('d', 20), array('e', 20)), - $this->redis->zrangebyscore('zset', 10, 20, array('withscores' => true)) - ); - - $this->assertEquals( - array('d', 'e'), - $this->redis->zrangebyscore('zset', 10, 20, array('limit' => array(1, 2))) - ); - - $this->assertEquals( - array('d', 'e'), - $this->redis->zrangebyscore('zset', 10, 20, array( - 'limit' => array('offset' => 1, 'count' => 2) - )) - ); - - $this->assertEquals( - array(array('d', 20), array('e', 20)), - $this->redis->zrangebyscore('zset', 10, 20, array( - 'limit' => array(1, 2), - 'withscores' => true, - )) - ); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zrangebyscore('foo', 0, 0); - }); - } - - function testZsetReverseRangeByScore() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals( - array('a'), - $this->redis->zrevrangebyscore('zset', -10, -10) - ); - - $this->assertEquals( - array('b', 'a'), - $this->redis->zrevrangebyscore('zset', 0, -10) - ); - - $this->assertEquals( - array('e', 'd'), - $this->redis->zrevrangebyscore('zset', 20, 20) - ); - - $this->assertEquals( - array('f', 'e', 'd', 'c', 'b'), - $this->redis->zrevrangebyscore('zset', 30, 0) - ); - - $this->assertEquals( - array(array('e', 20), array('d', 20), array('c', 10)), - $this->redis->zrevrangebyscore('zset', 20, 10, 'withscores') - ); - - $this->assertEquals( - array(array('e', 20), array('d', 20), array('c', 10)), - $this->redis->zrevrangebyscore('zset', 20, 10, array('withscores' => true)) - ); - - $this->assertEquals( - array('d', 'c'), - $this->redis->zrevrangebyscore('zset', 20, 10, array('limit' => array(1, 2))) - ); - - $this->assertEquals( - array('d', 'c'), - $this->redis->zrevrangebyscore('zset', 20, 10, array( - 'limit' => array('offset' => 1, 'count' => 2) - )) - ); - - $this->assertEquals( - array(array('d', 20), array('c', 10)), - $this->redis->zrevrangebyscore('zset', 20, 10, array( - 'limit' => array(1, 2), - 'withscores' => true, - )) - ); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zrevrangebyscore('foo', 0, 0); - }); - } - - function testZsetUnionStore() - { - $zsetA = RC::zsetAddAndReturn($this->redis, 'zseta', array('a' => 1, 'b' => 2, 'c' => 3)); - $zsetB = RC::zsetAddAndReturn($this->redis, 'zsetb', array('b' => 1, 'c' => 2, 'd' => 3)); - - // basic ZUNIONSTORE - $this->assertEquals(4, $this->redis->zunionstore('zsetc', 2, 'zseta', 'zsetb')); - $this->assertEquals( - array(array('a', 1), array('b', 3), array('d', 3), array('c', 5)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - $this->assertEquals(3, $this->redis->zunionstore('zsetc', 2, 'zseta', 'zsetbNull')); - $this->assertEquals( - array(array('a', 1), array('b', 2), array('c', 3)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - $this->assertEquals(3, $this->redis->zunionstore('zsetc', 2, 'zsetaNull', 'zsetb')); - $this->assertEquals( - array(array('b', 1), array('c', 2), array('d', 3)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - $this->assertEquals(0, $this->redis->zunionstore('zsetc', 2, 'zsetaNull', 'zsetbNull')); - - // with WEIGHTS - $options = array('weights' => array(2, 3)); - $this->assertEquals(4, $this->redis->zunionstore('zsetc', 2, 'zseta', 'zsetb', $options)); - $this->assertEquals( - array(array('a', 2), array('b', 7), array('d', 9), array('c', 12)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // with AGGREGATE (min) - $options = array('aggregate' => 'min'); - $this->assertEquals(4, $this->redis->zunionstore('zsetc', 2, 'zseta', 'zsetb', $options)); - $this->assertEquals( - array(array('a', 1), array('b', 1), array('c', 2), array('d', 3)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // with AGGREGATE (max) - $options = array('aggregate' => 'max'); - $this->assertEquals(4, $this->redis->zunionstore('zsetc', 2, 'zseta', 'zsetb', $options)); - $this->assertEquals( - array(array('a', 1), array('b', 2), array('c', 3), array('d', 3)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // using an array to pass the list of source keys - $sourceKeys = array('zseta', 'zsetb'); - - $this->assertEquals(4, $this->redis->zunionstore('zsetc', $sourceKeys)); - $this->assertEquals( - array(array('a', 1), array('b', 3), array('d', 3), array('c', 5)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // using an array to pass the list of source keys + options array - $options = array('weights' => array(2, 3)); - $this->assertEquals(4, $this->redis->zunionstore('zsetc', $sourceKeys, $options)); - $this->assertEquals( - array(array('a', 2), array('b', 7), array('d', 9), array('c', 12)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('zsetFake', 'fake'); - $test->redis->zunionstore('zsetc', 2, 'zseta', 'zsetFake'); - }); - } - - function testZsetIntersectionStore() - { - $zsetA = RC::zsetAddAndReturn($this->redis, 'zseta', array('a' => 1, 'b' => 2, 'c' => 3)); - $zsetB = RC::zsetAddAndReturn($this->redis, 'zsetb', array('b' => 1, 'c' => 2, 'd' => 3)); - - // basic ZINTERSTORE - $this->assertEquals(2, $this->redis->zinterstore('zsetc', 2, 'zseta', 'zsetb')); - $this->assertEquals( - array(array('b', 3), array('c', 5)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - $this->assertEquals(0, $this->redis->zinterstore('zsetc', 2, 'zseta', 'zsetbNull')); - $this->assertEquals(0, $this->redis->zinterstore('zsetc', 2, 'zsetaNull', 'zsetb')); - $this->assertEquals(0, $this->redis->zinterstore('zsetc', 2, 'zsetaNull', 'zsetbNull')); - - // with WEIGHTS - $options = array('weights' => array(2, 3)); - $this->assertEquals(2, $this->redis->zinterstore('zsetc', 2, 'zseta', 'zsetb', $options)); - $this->assertEquals( - array(array('b', 7), array('c', 12)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // with AGGREGATE (min) - $options = array('aggregate' => 'min'); - $this->assertEquals(2, $this->redis->zinterstore('zsetc', 2, 'zseta', 'zsetb', $options)); - $this->assertEquals( - array(array('b', 1), array('c', 2)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // with AGGREGATE (max) - $options = array('aggregate' => 'max'); - $this->assertEquals(2, $this->redis->zinterstore('zsetc', 2, 'zseta', 'zsetb', $options)); - $this->assertEquals( - array(array('b', 2), array('c', 3)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // using an array to pass the list of source keys - $sourceKeys = array('zseta', 'zsetb'); - - $this->assertEquals(2, $this->redis->zinterstore('zsetc', $sourceKeys)); - $this->assertEquals( - array(array('b', 3), array('c', 5)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - // using an array to pass the list of source keys + options array - $options = array('weights' => array(2, 3)); - $this->assertEquals(2, $this->redis->zinterstore('zsetc', $sourceKeys, $options)); - $this->assertEquals( - array(array('b', 7), array('c', 12)), - $this->redis->zrange('zsetc', 0, -1, 'withscores') - ); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('zsetFake', 'fake'); - $test->redis->zinterstore('zsetc', 2, 'zseta', 'zsetFake'); - }); - } - - function testZsetCount() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals(0, $this->redis->zcount('zset', 50, 100)); - $this->assertEquals(6, $this->redis->zcount('zset', -100, 100)); - $this->assertEquals(3, $this->redis->zcount('zset', 10, 20)); - $this->assertEquals(2, $this->redis->zcount('zset', "(10", 20)); - $this->assertEquals(1, $this->redis->zcount('zset', 10, "(20")); - $this->assertEquals(0, $this->redis->zcount('zset', "(10", "(20")); - $this->assertEquals(3, $this->redis->zcount('zset', "(0", "(30")); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zcount('foo', 0, 0); - }); - } - - function testZsetCardinality() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals(count($zset), $this->redis->zcard('zset')); - - $this->redis->zrem('zset', 'a'); - $this->assertEquals(count($zset) - 1, $this->redis->zcard('zset')); - - // empty zset - $this->redis->zadd('zsetB', 0, 'a'); - $this->redis->zrem('zsetB', 'a'); - $this->assertEquals(0, $this->redis->zcard('setB')); - - // non-existing zset - $this->assertEquals(0, $this->redis->zcard('zsetDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zcard('foo'); - }); - } - - function testZsetScore() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals(-10, $this->redis->zscore('zset', 'a')); - $this->assertEquals(10, $this->redis->zscore('zset', 'c')); - $this->assertEquals(20, $this->redis->zscore('zset', 'e')); - - $this->assertNull($this->redis->zscore('zset', 'x')); - $this->assertNull($this->redis->zscore('zsetDoesNotExist', 'a')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zscore('foo', 'bar'); - }); - } - - function testZsetRemoveRangeByScore() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals(2, $this->redis->zremrangebyscore('zset', -10, 0)); - $this->assertEquals( - array('c', 'd', 'e', 'f'), - $this->redis->zrange('zset', 0, -1) - ); - - $this->assertEquals(1, $this->redis->zremrangebyscore('zset', 10, 10)); - $this->assertEquals( - array('d', 'e', 'f'), - $this->redis->zrange('zset', 0, -1) - ); - - $this->assertEquals(0, $this->redis->zremrangebyscore('zset', 100, 100)); - - $this->assertEquals(3, $this->redis->zremrangebyscore('zset', 0, 100)); - $this->assertEquals(0, $this->redis->zremrangebyscore('zset', 0, 100)); - - $this->assertEquals(0, $this->redis->zremrangebyscore('zsetDoesNotExist', 0, 100)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zremrangebyscore('foo', 0, 0); - }); - } - - function testZsetRank() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals(0, $this->redis->zrank('zset', 'a')); - $this->assertEquals(1, $this->redis->zrank('zset', 'b')); - $this->assertEquals(4, $this->redis->zrank('zset', 'e')); - - $this->redis->zrem('zset', 'd'); - $this->assertEquals(3, $this->redis->zrank('zset', 'e')); - - $this->assertNull($this->redis->zrank('zset', 'x')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zrank('foo', 'a'); - }); - } - - function testZsetReverseRank() - { - $zset = RC::zsetAddAndReturn($this->redis, 'zset', RC::getZSetArray()); - - $this->assertEquals(5, $this->redis->zrevrank('zset', 'a')); - $this->assertEquals(4, $this->redis->zrevrank('zset', 'b')); - $this->assertEquals(1, $this->redis->zrevrank('zset', 'e')); - - $this->redis->zrem('zset', 'e'); - $this->assertEquals(1, $this->redis->zrevrank('zset', 'd')); - - $this->assertNull($this->redis->zrevrank('zset', 'x')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zrevrank('foo', 'a'); - }); - } - - function testZsetRemoveRangeByRank() - { - RC::zsetAddAndReturn($this->redis, 'zseta', RC::getZSetArray()); - - $this->assertEquals(3, $this->redis->zremrangebyrank('zseta', 0, 2)); - $this->assertEquals( - array('d', 'e', 'f'), - $this->redis->zrange('zseta', 0, -1) - ); - - $this->assertEquals(1, $this->redis->zremrangebyrank('zseta', 0, 0)); - $this->assertEquals( - array('e', 'f'), - $this->redis->zrange('zseta', 0, -1) - ); - - RC::zsetAddAndReturn($this->redis, 'zsetb', RC::getZSetArray()); - $this->assertEquals(3, $this->redis->zremrangebyrank('zsetb', -3, -1)); - $this->assertEquals( - array('a', 'b', 'c'), - $this->redis->zrange('zsetb', 0, -1) - ); - - $this->assertEquals(1, $this->redis->zremrangebyrank('zsetb', -1, -1)); - $this->assertEquals( - array('a', 'b'), - $this->redis->zrange('zsetb', 0, -1) - ); - - $this->assertEquals(2, $this->redis->zremrangebyrank('zsetb', -2, 1)); - $this->assertEquals( - array(), - $this->redis->zrange('zsetb', 0, -1) - ); - $this->assertFalse($this->redis->exists('zsetb')); - - $this->assertEquals(0, $this->redis->zremrangebyrank('zsetc', 0, 0)); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->zremrangebyrank('foo', 0, 1); - }); - } - - /* commands operating on hashes */ - - function testHashSet() - { - $this->assertTrue($this->redis->hset('metavars', 'foo', 'bar')); - $this->assertTrue($this->redis->hset('metavars', 'hoge', 'piyo')); - $this->assertEquals('bar', $this->redis->hget('metavars', 'foo')); - $this->assertEquals('piyo', $this->redis->hget('metavars', 'hoge')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('test', 'foobar'); - $test->redis->hset('test', 'hoge', 'piyo'); - }); - } - - function testHashGet() - { - $this->assertTrue($this->redis->hset('metavars', 'foo', 'bar')); - $this->assertEquals('bar', $this->redis->hget('metavars', 'foo')); - - $this->assertEquals('bar', $this->redis->hget('metavars', 'foo')); - $this->assertNull($this->redis->hget('metavars', 'hoge')); - $this->assertNull($this->redis->hget('hashDoesNotExist', 'field')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->rpush('metavars', 'foo'); - $test->redis->hget('metavars', 'foo'); - }); - } - - function testHashExists() - { - $this->assertTrue($this->redis->hset('metavars', 'foo', 'bar')); - $this->assertTrue($this->redis->hexists('metavars', 'foo')); - $this->assertFalse($this->redis->hexists('metavars', 'hoge')); - $this->assertFalse($this->redis->hexists('hashDoesNotExist', 'field')); - } - - function testHashDelete() - { - $this->assertTrue($this->redis->hset('metavars', 'foo', 'bar')); - $this->assertTrue($this->redis->hexists('metavars', 'foo')); - $this->assertTrue($this->redis->hdel('metavars', 'foo')); - $this->assertFalse($this->redis->hexists('metavars', 'foo')); - - $this->assertFalse($this->redis->hdel('metavars', 'hoge')); - $this->assertFalse($this->redis->hdel('hashDoesNotExist', 'field')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->hdel('foo', 'field'); - }); - } - - function testHashLength() - { - $this->assertTrue($this->redis->hset('metavars', 'foo', 'bar')); - $this->assertTrue($this->redis->hset('metavars', 'hoge', 'piyo')); - $this->assertTrue($this->redis->hset('metavars', 'foofoo', 'barbar')); - $this->assertTrue($this->redis->hset('metavars', 'hogehoge', 'piyopiyo')); - - $this->assertEquals(4, $this->redis->hlen('metavars')); - $this->assertEquals(0, $this->redis->hlen('hashDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->hlen('foo'); - }); - } - - function testHashSetPreserve() - { - $this->assertTrue($this->redis->hsetnx('metavars', 'foo', 'bar')); - $this->assertFalse($this->redis->hsetnx('metavars', 'foo', 'barbar')); - $this->assertEquals('bar', $this->redis->hget('metavars', 'foo')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('test', 'foobar'); - $test->redis->hsetnx('test', 'hoge', 'piyo'); - }); - } - - function testHashSetAndGetMultiple() - { - $hashKVs = array('foo' => 'bar', 'hoge' => 'piyo'); - - // key=>value pairs via array instance - $this->assertTrue($this->redis->hmset('metavars', $hashKVs)); - $multiRet = $this->redis->hmget('metavars', array_keys($hashKVs)); - $this->assertEquals($hashKVs, array_combine(array_keys($hashKVs), array_values($multiRet))); - - // key=>value pairs via function arguments - $this->redis->del('metavars'); - $this->assertTrue($this->redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo')); - $this->assertEquals(array('bar', 'piyo'), $this->redis->hmget('metavars', 'foo', 'hoge')); - } - - function testHashIncrementBy() - { - // test subsequent increment commands - $this->assertEquals(10, $this->redis->hincrby('hash', 'counter', 10)); - $this->assertEquals(20, $this->redis->hincrby('hash', 'counter', 10)); - $this->assertEquals(0, $this->redis->hincrby('hash', 'counter', -20)); - - RC::testForServerException($this, RC::EXCEPTION_HASH_VALNOTINT, function($test) { - $test->redis->hset('hash', 'field', 'stringvalue'); - $test->redis->hincrby('hash', 'field', 10); - }); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->hincrby('foo', 'bar', 1); - }); - } - - function testHashKeys() - { - $hashKVs = array('foo' => 'bar', 'hoge' => 'piyo'); - $this->assertTrue($this->redis->hmset('metavars', $hashKVs)); - - $this->assertEquals(array_keys($hashKVs), $this->redis->hkeys('metavars')); - $this->assertEquals(array(), $this->redis->hkeys('hashDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->hkeys('foo'); - }); - } - - function testHashValues() - { - $hashKVs = array('foo' => 'bar', 'hoge' => 'piyo'); - $this->assertTrue($this->redis->hmset('metavars', $hashKVs)); - - $this->assertEquals(array_values($hashKVs), $this->redis->hvals('metavars')); - $this->assertEquals(array(), $this->redis->hvals('hashDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->hvals('foo'); - }); - } - - function testHashGetAll() - { - $hashKVs = array('foo' => 'bar', 'hoge' => 'piyo'); - $this->assertTrue($this->redis->hmset('metavars', $hashKVs)); - - $this->assertEquals($hashKVs, $this->redis->hgetall('metavars')); - $this->assertEquals(array(), $this->redis->hgetall('hashDoesNotExist')); - - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->hgetall('foo'); - }); - } - - /* multiple databases handling commands */ - - function testSelectDatabase() - { - $this->assertTrue($this->redis->select(0)); - $this->assertTrue($this->redis->select(RC::DEFAULT_DATABASE)); - - RC::testForServerException($this, RC::EXCEPTION_INVALID_DB_IDX, function($test) { - $test->redis->select(32); - }); - - RC::testForServerException($this, RC::EXCEPTION_INVALID_DB_IDX, function($test) { - $test->redis->select(-1); - }); - } - - function testMove() - { - // TODO: This test sucks big time. Period. - $otherDb = 5; - $this->redis->set('foo', 'bar'); - - $this->redis->select($otherDb); - $this->redis->flushdb(); - $this->redis->select(RC::DEFAULT_DATABASE); - - $this->assertTrue($this->redis->move('foo', $otherDb)); - $this->assertFalse($this->redis->move('foo', $otherDb)); - $this->assertFalse($this->redis->move('keyDoesNotExist', $otherDb)); - - $this->redis->set('hoge', 'piyo'); - // TODO: shouldn't Redis send an EXCEPTION_INVALID_DB_IDX instead of EXCEPTION_OUT_OF_RANGE? - RC::testForServerException($this, RC::EXCEPTION_OUT_OF_RANGE, function($test) { - $test->redis->move('hoge', 32); - }); - } - - function testFlushdb() - { - $this->assertTrue($this->redis->flushdb()); - } - - /* sorting */ - - function testSort() - { - $unorderedList = RC::pushTailAndReturn($this->redis, 'unordered', array(2, 100, 3, 1, 30, 10)); - - // without parameters - $this->assertEquals(array(1, 2, 3, 10, 30, 100), $this->redis->sort('unordered')); - - // with parameter ASC/DESC - $this->assertEquals( - array(100, 30, 10, 3, 2, 1), - $this->redis->sort('unordered', array( - 'sort' => 'desc' - )) - ); - - // with parameter LIMIT - $this->assertEquals( - array(1, 2, 3), - $this->redis->sort('unordered', array( - 'limit' => array(0, 3) - )) - ); - $this->assertEquals( - array(10, 30), - $this->redis->sort('unordered', array( - 'limit' => array(3, 2) - )) - ); - - // with parameter ALPHA - $this->assertEquals( - array(1, 10, 100, 2, 3, 30), - $this->redis->sort('unordered', array( - 'alpha' => true - )) - ); - - // with combined parameters - $this->assertEquals( - array(30, 10, 3, 2), - $this->redis->sort('unordered', array( - 'alpha' => false, - 'sort' => 'desc', - 'limit' => array(1, 4) - )) - ); - - // with parameter ALPHA - $this->assertEquals( - array(1, 10, 100, 2, 3, 30), - $this->redis->sort('unordered', array( - 'alpha' => true - )) - ); - - // with parameter STORE - $this->assertEquals( - count($unorderedList), - $this->redis->sort('unordered', array( - 'store' => 'ordered' - )) - ); - $this->assertEquals(array(1, 2, 3, 10, 30, 100), $this->redis->lrange('ordered', 0, -1)); - - // with parameter GET - $this->redis->rpush('uids', 1003); - $this->redis->rpush('uids', 1001); - $this->redis->rpush('uids', 1002); - $this->redis->rpush('uids', 1000); - $sortget = array( - 'uid:1000' => 'foo', 'uid:1001' => 'bar', - 'uid:1002' => 'hoge', 'uid:1003' => 'piyo' - ); - $this->redis->mset($sortget); - $this->assertEquals( - array_values($sortget), - $this->redis->sort('uids', array('get' => 'uid:*')) - ); - - // wrong type - RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, function($test) { - $test->redis->set('foo', 'bar'); - $test->redis->sort('foo'); - }); - } - - /* remote server control commands */ - - function testInfo() - { - $serverInfo = $this->redis->info(); - - $this->assertInternalType('array', $serverInfo); - $this->assertNotNull($serverInfo['redis_version']); - $this->assertGreaterThan(0, $serverInfo['uptime_in_seconds']); - $this->assertGreaterThan(0, $serverInfo['total_connections_received']); - } - - function testSlaveOf() - { - $masterHost = 'www.google.com'; - $masterPort = 80; - - $this->assertTrue($this->redis->slaveof($masterHost, $masterPort)); - - // slave of NO ONE, the implicit way - $this->assertTrue($this->redis->slaveof()); - - // slave of NO ONE, the explicit way - $this->assertTrue($this->redis->slaveof('NO ONE')); - } - - /* persistence control commands */ - - function testSave() - { - $this->assertTrue($this->redis->save()); - } - - function testBackgroundSave() - { - $this->assertTrue($this->redis->bgsave()); - sleep(1); - } - - function testBackgroundRewriteAppendOnlyFile() - { - $this->assertTrue($this->redis->bgrewriteaof()); - } - - function testLastSave() - { - $this->assertGreaterThan(0, $this->redis->lastsave()); - } -} diff --git a/tests/PHPUnit/ArrayHasSameValuesConstraint.php b/tests/PHPUnit/ArrayHasSameValuesConstraint.php new file mode 100644 index 00000000..8fa3d3e7 --- /dev/null +++ b/tests/PHPUnit/ArrayHasSameValuesConstraint.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use \PHPUnit_Framework_Constraint; +use \PHPUnit_Framework_ExpectationFailedException; + +/** + * Constraint that accepts arrays with the same elements but different order. + */ +class ArrayHasSameValuesConstraint extends PHPUnit_Framework_Constraint +{ + protected $array; + + /** + * @param array $array + */ + public function __construct($array) + { + $this->array = $array; + } + + /** + * {@inheritdoc} + */ + public function evaluate($other) + { + if (count($this->array) !== count($other)) { + throw new PHPUnit_Framework_ExpectationFailedException('Failed asserting that two arrays have the same elements.'); + } + if (array_diff($this->array, $other)) { + throw new PHPUnit_Framework_ExpectationFailedException('Failed asserting that two arrays have the same elements.'); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function toString() + { + return 'two arrays have the same elements.'; + } +} \ No newline at end of file diff --git a/tests/PHPUnit/CommandTestCase.php b/tests/PHPUnit/CommandTestCase.php new file mode 100644 index 00000000..0a144910 --- /dev/null +++ b/tests/PHPUnit/CommandTestCase.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; +use Predis\Profiles\ServerProfile; +use Predis\Profiles\IServerProfile; + +/** + * + */ +abstract class CommandTestCase extends StandardTestCase +{ + /** + * Returns the expected command. + * + * @return ICommand|string Instance or FQN of the expected command. + */ + protected abstract function getExpectedCommand(); + + /** + * Returns the expected command ID. + * + * @return string + */ + protected abstract function getExpectedId(); + + /** + * Returns a new command instance. + * + * @return ICommand + */ + protected function getCommand() + { + $command = $this->getExpectedCommand(); + + return $command instanceof ICommand ? $command : new $command(); + } + + /** + * Return the server profile used during the tests. + * + * @return IServerProfile + */ + protected function getProfile() + { + return ServerProfile::get(REDIS_SERVER_VERSION); + } + + /** + * Returns a new client instance. + * + * @param Boolean $connect Flush selected database before returning the client. + * @return Client + */ + protected function getClient($flushdb = true) + { + $profile = $this->getProfile(); + + if (!$profile->supportsCommand($id = $this->getExpectedId())) { + $this->markTestSkipped("The profile {$profile->getVersion()} does not support command {$id}"); + } + + $parameters = array( + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + ); + + $options = array( + 'profile' => $profile + ); + + $client = new Client($parameters, $options); + $client->connect(); + $client->select(REDIS_SERVER_DBNUM); + + if ($flushdb) { + $client->flushdb(); + } + + return $client; + } + + /** + * Returns wether the command is prefixable or not. + * + * @return Boolean + */ + protected function isPrefixable() + { + return $this->getCommand() instanceof IPrefixable; + } + + /** + * Returns a new command instance with the specified arguments. + * + * @param ... List of arguments for the command. + * @return ICommand + */ + protected function getCommandWithArguments(/* arguments */) + { + return $this->getCommandWithArgumentsArray(func_get_args()); + } + + /** + * Returns a new command instance with the specified arguments. + * + * @param array $arguments Arguments for the command. + * @return ICommand + */ + protected function getCommandWithArgumentsArray(Array $arguments) + { + $command = $this->getCommand(); + $command->setArguments($arguments); + + return $command; + } + + /** + * Sleep the test case with microseconds resolution. + * + * @param float $seconds Seconds to sleep. + */ + protected function sleep($seconds) + { + usleep($seconds * 1000000); + } + + /** + * Asserts that two arrays have the same values, even if with different order. + * + * @param Array $expected Expected array. + * @param Array $actual Actual array. + */ + protected function assertSameValues(Array $expected, Array $actual) + { + $this->assertThat($expected, new \ArrayHasSameValuesConstraint($actual)); + } + + /** + * @group disconnected + */ + public function testCommandId() + { + $command = $this->getCommand(); + + $this->assertInstanceOf('Predis\Commands\ICommand', $command); + $this->assertEquals($this->getExpectedId(), $command->getId()); + } + + /** + * @group disconnected + */ + public function testRawArguments() + { + $expected = array('1st', '2nd', '3rd', '4th'); + + $command = $this->getCommand(); + $command->setRawArguments($expected); + + $this->assertSame($expected, $command->getArguments()); + } +} diff --git a/tests/PHPUnit/ConnectionTestCase.php b/tests/PHPUnit/ConnectionTestCase.php new file mode 100644 index 00000000..fa83edc3 --- /dev/null +++ b/tests/PHPUnit/ConnectionTestCase.php @@ -0,0 +1,387 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Network; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\ConnectionParameters; +use Predis\Profiles\ServerProfile; + +/** + * @group realm-network + */ +abstract class ConnectionTestCase extends StandardTestCase +{ + /** + * @group disconnected + * @group slow + * @expectedException Predis\Network\ConnectionException + */ + public function testThrowExceptionWhenUnableToConnect() + { + $parameters = array('host' => '169.254.10.10', 'connection_timeout' => 0.5); + $connection = $this->getConnection($profile, false, $parameters); + $connection->executeCommand($this->getProfile()->createCommand('ping')); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testConnectForcesConnection() + { + $connection = $this->getConnection(); + + $this->assertFalse($connection->isConnected()); + $connection->connect(); + $this->assertTrue($connection->isConnected()); + } + + /** + * @group connected + * @expectedException Predis\ClientException + * @expectedExceptionMessage Connection already estabilished + */ + public function testThrowsExceptionOnConnectWhenAlreadyConnected() + { + $connection = $this->getConnection(); + + $connection->connect(); + $connection->connect(); + } + + /** + * @group connected + */ + public function testDisconnectForcesDisconnection() + { + $connection = $this->getConnection(); + + $connection->connect(); + $this->assertTrue($connection->isConnected()); + + $connection->disconnect(); + $this->assertFalse($connection->isConnected()); + } + + /** + * @group disconnected + */ + public function testDoesNotThrowExceptionOnDisconnectWhenAlreadyDisconnected() + { + $connection = $this->getConnection(); + + $this->assertFalse($connection->isConnected()); + $connection->disconnect(); + $this->assertFalse($connection->isConnected()); + } + + /** + * @group connected + */ + public function testGetResourceForcesConnection() + { + $connection = $this->getConnection(); + + $this->assertFalse($connection->isConnected()); + $this->assertInternalType('resource', $connection->getResource()); + $this->assertTrue($connection->isConnected()); + } + + /** + * @group connected + */ + public function testSendingCommandForcesConnection() + { + $connection = $this->getConnection($profile); + $cmdPing = $profile->createCommand('ping'); + + $this->assertTrue($connection->executeCommand($cmdPing)); + $this->assertTrue($connection->isConnected()); + } + + /** + * @group connected + */ + public function testExecutesCommandOnServer() + { + $connection = $this->getConnection($profile); + + $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse')); + $cmdPing->expects($this->once()) + ->method('parseResponse') + ->with('PONG') + ->will($this->returnValue(true)); + + $this->assertTrue($connection->executeCommand($cmdPing)); + } + + /** + * @group connected + */ + public function testWritesCommandToServer() + { + $connection = $this->getConnection($profile); + + $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse')); + $cmdPing->expects($this->never()) + ->method('parseResponse'); + + $connection->writeCommand($cmdPing); + $connection->disconnect(); + } + + /** + * @group connected + */ + public function testReadsCommandFromServer() + { + $connection = $this->getConnection($profile); + + $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse')); + $cmdPing->expects($this->once()) + ->method('parseResponse') + ->with('PONG') + ->will($this->returnValue(true)); + + $connection->writeCommand($cmdPing); + $this->assertTrue($connection->readResponse($cmdPing)); + } + + /** + * @group connected + */ + public function testIsAbleToWriteMultipleCommandsAndReadThemBackForPipelining() + { + $connection = $this->getConnection($profile); + + $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse')); + $cmdPing->expects($this->once()) + ->method('parseResponse') + ->with('PONG') + ->will($this->returnValue(true)); + + $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('parseResponse')); + $cmdEcho->setArguments(array('ECHOED')); + $cmdEcho->expects($this->once()) + ->method('parseResponse') + ->with('ECHOED') + ->will($this->returnValue('ECHOED')); + + $connection = $this->getConnection(); + + $connection->writeCommand($cmdPing); + $connection->writeCommand($cmdEcho); + + $this->assertTrue($connection->readResponse($cmdPing)); + $this->assertSame('ECHOED', $connection->readResponse($cmdEcho)); + } + + /** + * @group connected + */ + public function testSendsInitializationCommandsOnConnection() + { + $connection = $this->getConnection($profile, true); + + $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse')); + $cmdPing->expects($this->once()) + ->method('parseResponse') + ->with('PONG') + ->will($this->returnValue(true)); + + $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('parseResponse')); + $cmdEcho->setArguments(array('ECHOED')); + $cmdEcho->expects($this->once()) + ->method('parseResponse') + ->with('ECHOED') + ->will($this->returnValue('ECHOED')); + + $connection->pushInitCommand($cmdPing); + $connection->pushInitCommand($cmdEcho); + + $connection->connect(); + } + + /** + * @group connected + */ + public function testReadsStatusReplies() + { + $connection = $this->getConnection($profile, true); + + $connection->writeCommand($profile->createCommand('set', array('foo', 'bar'))); + $this->assertTrue($connection->read()); + + $connection->writeCommand($profile->createCommand('ping')); + $this->assertSame('PONG', $connection->read()); + + $connection->writeCommand($profile->createCommand('multi')); + $connection->writeCommand($profile->createCommand('ping')); + $this->assertTrue($connection->read()); + $this->assertInstanceOf('Predis\ResponseQueued', $connection->read()); + } + + /** + * @group connected + */ + public function testReadsBulkReplies() + { + $connection = $this->getConnection($profile, true); + + $connection->executeCommand($profile->createCommand('set', array('foo', 'bar'))); + + $connection->writeCommand($profile->createCommand('get', array('foo'))); + $this->assertSame('bar', $connection->read()); + + $connection->writeCommand($profile->createCommand('get', array('hoge'))); + $this->assertNull($connection->read()); + } + + /** + * @group connected + */ + public function testReadsIntegerReplies() + { + $connection = $this->getConnection($profile, true); + + $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol'))); + $connection->writeCommand($profile->createCommand('llen', array('metavars'))); + + $this->assertSame(3, $connection->read()); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testReadsErrorRepliesAsExceptions() + { + $connection = $this->getConnection($profile, true, array('throw_errors' => true)); + + $connection->executeCommand($profile->createCommand('set', array('foo', 'bar'))); + $connection->writeCommand($profile->createCommand('rpush', array('foo', 'baz'))); + + $connection->read(); + } + + /** + * @group connected + */ + public function testReadsErrorRepliesAsResponseErrorObjects() + { + $connection = $this->getConnection($profile, true, array('throw_errors' => false)); + + $connection->executeCommand($profile->createCommand('set', array('foo', 'bar'))); + $connection->writeCommand($profile->createCommand('rpush', array('foo', 'baz'))); + + $this->assertInstanceOf('Predis\ResponseError', $error = $connection->read()); + $this->assertSame('ERR Operation against a key holding the wrong kind of value', $error->getMessage()); + } + + /** + * @group connected + */ + public function testReadsMultibulkRepliesAsArrays() + { + $connection = $this->getConnection($profile, true); + + $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol'))); + $connection->writeCommand($profile->createCommand('lrange', array('metavars', 0, -1))); + + $this->assertSame(array('foo', 'hoge', 'lol'), $connection->read()); + } + + /** + * @group connected + * @group slow + * @expectedException Predis\Network\ConnectionException + * @expectedExceptionMessage Connection timed out + */ + public function testThrowsExceptionOnConnectionTimeout() + { + $connection = $this->getConnection($_, false, array('host' => '169.254.10.10', 'connection_timeout' => 0.5)); + + $connection->connect(); + } + + /** + * @group connected + * @group slow + * @expectedException Predis\Network\ConnectionException + */ + public function testThrowsExceptionOnReadWriteTimeout() + { + $connection = $this->getConnection($profile, true, array('read_write_timeout' => 0.5)); + + $connection->executeCommand($profile->createCommand('brpop', array('foo', 3))); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a named array with the default connection parameters and their values. + * + * @return Array Default connection parameters. + */ + protected function getDefaultParametersArray() + { + return array( + 'scheme' => 'tcp', + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'database' => REDIS_SERVER_DBNUM, + 'read_write_timeout' => 2, + ); + } + + /** + * Returns a new instance of connection parameters. + * + * @param array $additional Additional connection parameters. + * @return ConnectionParameters Default connection parameters. + */ + protected function getParameters($additional = array()) + { + $parameters = array_merge($this->getDefaultParametersArray(), $additional); + $parameters = new ConnectionParameters($parameters); + + return $parameters; + } + + /** + * Returns a new instance of server profile. + * + * @param array $additional Additional connection parameters. + * @return ServerProfile + */ + protected function getProfile($version = null) + { + return ServerProfile::get($version ?: REDIS_SERVER_VERSION); + } + + /** + * Returns a new instance of a connection instance. + * + * @param ServerProfile $profile Reference to the server profile instance. + * @param Boolean $initialize Push default initialization commands (SELECT and FLUSHDB). + * @param array $parameters Additional connection parameters. + * @return StreamConnection + */ + protected abstract function getConnection(&$profile = null, $initialize = false, Array $parameters = array()); +} diff --git a/tests/PHPUnit/DistributionStrategyTestCase.php b/tests/PHPUnit/DistributionStrategyTestCase.php new file mode 100644 index 00000000..3cd1623c --- /dev/null +++ b/tests/PHPUnit/DistributionStrategyTestCase.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Distribution; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +abstract class DistributionStrategyTestCase extends StandardTestCase +{ + /** + * Returns a new instance of the tested distributor. + * + * @return Predis\Distribution\IDistributionStrategy + */ + protected abstract function getDistributorInstance(); + + /** + * Returns a list of nodes from the hashring. + * + * @param IDistributionStrategy $ring Hashring instance. + * @param int $iterations Number of nodes to fetch. + * @return array Nodes from the hashring. + */ + protected function getNodes(IDistributionStrategy $ring, $iterations = 10) + { + $nodes = array(); + + for ($i = 0; $i < $iterations; $i++) { + $key = $ring->generateKey($i * $i); + $nodes[] = $ring->get($key); + } + + return $nodes; + } + + /** + * @group disconnected + */ + public function testEmptyRingThrowsException() + { + $this->setExpectedException('Predis\Distribution\EmptyRingException'); + + $ring = $this->getDistributorInstance(); + $ring->get('nodekey'); + } + + /** + * @group disconnected + */ + public function testRemoveOnEmptyRingDoesNotThrowException() + { + $ring = $this->getDistributorInstance(); + + $this->assertNull($ring->remove('node')); + } +} diff --git a/tests/PHPUnit/ServerVersionTestCase.php b/tests/PHPUnit/ServerVersionTestCase.php new file mode 100644 index 00000000..5e19bad7 --- /dev/null +++ b/tests/PHPUnit/ServerVersionTestCase.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Profiles; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +abstract class ServerVersionTestCase extends StandardTestCase +{ + /** + * Returns a new instance of the tested profile. + * + * @return Predis\Profiles\IServerProfile + */ + protected abstract function getProfileInstance(); + + /** + * Returns the expected version string for the tested profile. + * + * @return string Version string. + */ + protected abstract function getExpectedVersion(); + + /** + * Returns the expected list of commands supported by the tested profile. + * + * @return array List of supported commands. + */ + protected abstract function getExpectedCommands(); + + /** + * Returns the list of commands supported by the current + * server profile. + * + * @param IServerProfile $profile Server profile instance. + * @return array + */ + protected function getCommands(IServerProfile $profile) + { + $commands = $profile->getSupportedCommands(); + + return array_keys($commands); + } + + /** + * @group disconnected + */ + public function testGetVersion() + { + $profile = $this->getProfileInstance(); + + $this->assertEquals($this->getExpectedVersion(), $profile->getVersion()); + } + + /** + * @group disconnected + */ + public function testSupportedCommands() + { + $profile = $this->getProfileInstance(); + $expected = $this->getExpectedCommands(); + $commands = $this->getCommands($profile); + + $this->assertSame($expected, $commands); + } +} diff --git a/tests/Predis/ClientExceptionTest.php b/tests/Predis/ClientExceptionTest.php new file mode 100644 index 00000000..13e6c94e --- /dev/null +++ b/tests/Predis/ClientExceptionTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ClientExceptionTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testExceptionMessage() + { + $message = 'This is a client exception.'; + + $this->setExpectedException('Predis\ClientException', $message); + + throw new ClientException($message); + } + + /** + * @group disconnected + */ + public function testExceptionClass() + { + $exception = new ClientException(); + + $this->assertInstanceOf('Predis\ClientException', $exception); + $this->assertInstanceOf('Predis\PredisException', $exception); + } +} diff --git a/tests/Predis/ClientTest.php b/tests/Predis/ClientTest.php new file mode 100644 index 00000000..6628e715 --- /dev/null +++ b/tests/Predis/ClientTest.php @@ -0,0 +1,647 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Profiles\ServerProfile; +use Predis\Network\PredisCluster; + +/** + * + */ +class ClientTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testConstructorWithoutArguments() + { + $client = new Client(); + + $connection = $client->getConnection(); + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + + $parameters = $connection->getParameters(); + $this->assertSame($parameters->host, '127.0.0.1'); + $this->assertSame($parameters->port, 6379); + + $options = $client->getOptions(); + $this->assertSame($options->profile->getVersion(), ServerProfile::getDefault()->getVersion()); + + $this->assertFalse($client->isConnected()); + } + + /** + * @group disconnected + */ + public function testConstructorWithNullArgument() + { + $client = new Client(null); + + $connection = $client->getConnection(); + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + + $parameters = $connection->getParameters(); + $this->assertSame($parameters->host, '127.0.0.1'); + $this->assertSame($parameters->port, 6379); + + $options = $client->getOptions(); + $this->assertSame($options->profile->getVersion(), ServerProfile::getDefault()->getVersion()); + + $this->assertFalse($client->isConnected()); + } + + /** + * @group disconnected + */ + public function testConstructorWithNullAndNullArguments() + { + $client = new Client(null, null); + + $connection = $client->getConnection(); + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + + $parameters = $connection->getParameters(); + $this->assertSame($parameters->host, '127.0.0.1'); + $this->assertSame($parameters->port, 6379); + + $options = $client->getOptions(); + $this->assertSame($options->profile->getVersion(), ServerProfile::getDefault()->getVersion()); + + $this->assertFalse($client->isConnected()); + } + + /** + * @group disconnected + */ + public function testConstructorWithArrayArgument() + { + $client = new Client($arg1 = array('host' => 'localhost', 'port' => 7000)); + + $parameters = $client->getConnection()->getParameters(); + $this->assertSame($parameters->host, $arg1['host']); + $this->assertSame($parameters->port, $arg1['port']); + } + + /** + * @group disconnected + */ + public function testConstructorWithArrayOfArrayArgument() + { + $arg1 = array( + array('host' => 'localhost', 'port' => 7000), + array('host' => 'localhost', 'port' => 7001), + ); + + $client = new Client($arg1); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $client->getConnection()); + } + + /** + * @group disconnected + */ + public function testConstructorWithStringArgument() + { + $client = new Client('tcp://localhost:7000'); + + $parameters = $client->getConnection()->getParameters(); + $this->assertSame($parameters->host, 'localhost'); + $this->assertSame($parameters->port, 7000); + } + + /** + * @group disconnected + */ + public function testConstructorWithArrayOfStringArgument() + { + $client = new Client($arg1 = array('tcp://localhost:7000', 'tcp://localhost:7001')); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $client->getConnection()); + } + + /** + * @group disconnected + */ + public function testConstructorWithArrayOfConnectionsArgument() + { + $connection1 = $this->getMock('Predis\Network\IConnectionSingle'); + $connection2 = $this->getMock('Predis\Network\IConnectionSingle'); + + $client = new Client(array($connection1, $connection2)); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $cluster = $client->getConnection()); + $this->assertSame($connection1, $cluster->getConnectionById(0)); + $this->assertSame($connection2, $cluster->getConnectionById(1)); + } + + /** + * @group disconnected + */ + public function testConstructorWithConnectionArgument() + { + $factory = new ConnectionFactory(); + $connection = $factory->create('tcp://localhost:7000'); + + $client = new Client($connection); + + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $client->getConnection()); + $this->assertSame($connection, $client->getConnection()); + + $parameters = $client->getConnection()->getParameters(); + $this->assertSame($parameters->host, 'localhost'); + $this->assertSame($parameters->port, 7000); + } + + /** + * @group disconnected + */ + public function testConstructorWithClusterArgument() + { + $cluster = new PredisCluster(); + + $factory = new ConnectionFactory(); + $factory->createCluster($cluster, array('tcp://localhost:7000', 'tcp://localhost:7001')); + + $client = new Client($cluster); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $client->getConnection()); + $this->assertSame($cluster, $client->getConnection()); + } + + /** + * @group disconnected + */ + public function testConstructorWithNullAndStringArgument() + { + $client = new Client(null, '2.0'); + + $this->assertSame($client->getProfile()->getVersion(), ServerProfile::get('2.0')->getVersion()); + } + + /** + * @group disconnected + */ + public function testConstructorWithNullAndProfileArgument() + { + $client = new Client(null, $arg2 = ServerProfile::get('2.0')); + + $this->assertSame($client->getProfile(), $arg2); + } + + /** + * @group disconnected + */ + public function testConstructorWithNullAndArrayArgument() + { + $factory = $this->getMock('Predis\IConnectionFactory'); + + $arg2 = array('profile' => '2.0', 'prefix' => 'prefix:', 'connections' => $factory); + $client = new Client(null, $arg2); + + $profile = $client->getProfile(); + $this->assertSame($profile->getVersion(), ServerProfile::get('2.0')->getVersion()); + $this->assertInstanceOf('Predis\Commands\Processors\KeyPrefixProcessor', $profile->getProcessor()); + $this->assertSame('prefix:', $profile->getProcessor()->getPrefix()); + + $this->assertSame($factory, $client->getConnectionFactory()); + } + + /** + * @group disconnected + */ + public function testConnectAndDisconnect() + { + $connection = $this->getMock('Predis\Network\IConnection'); + $connection->expects($this->once())->method('connect'); + $connection->expects($this->once())->method('disconnect'); + + $client = new Client($connection); + $client->connect(); + $client->disconnect(); + } + + /** + * @group disconnected + */ + public function testIsConnectedChecksConnectionState() + { + $connection = $this->getMock('Predis\Network\IConnection'); + $connection->expects($this->once())->method('isConnected'); + + $client = new Client($connection); + $client->isConnected(); + } + + /** + * @group disconnected + */ + public function testQuitIsAliasForDisconnect() + { + $connection = $this->getMock('Predis\Network\IConnection'); + $connection->expects($this->once())->method('disconnect'); + + $client = new Client($connection); + $client->quit(); + } + + /** + * @group disconnected + */ + public function testCreatesNewCommandUsingSpecifiedProfile() + { + $ping = ServerProfile::getDefault()->createCommand('ping', array()); + + $profile = $this->getMock('Predis\Profiles\IServerProfile'); + $profile->expects($this->once()) + ->method('createCommand') + ->with('ping', array()) + ->will($this->returnValue($ping)); + + $client = new Client(null, $profile); + $this->assertSame($ping, $client->createCommand('ping', array())); + } + + /** + * @group disconnected + */ + public function testExecuteCommand() + { + $ping = ServerProfile::getDefault()->createCommand('ping', array()); + + $connection= $this->getMock('Predis\Network\IConnection'); + $connection->expects($this->once()) + ->method('executeCommand') + ->with($ping) + ->will($this->returnValue(true)); + + $client = new Client($connection); + + $this->assertTrue($client->executeCommand($ping)); + } + + /** + * @group disconnected + */ + public function testExecuteCommandOnEachNode() + { + $ping = ServerProfile::getDefault()->createCommand('ping', array()); + + $connection1 = $this->getMock('Predis\Network\IConnectionSingle'); + $connection1->expects($this->once()) + ->method('executeCommand') + ->with($ping) + ->will($this->returnValue(true)); + + $connection2 = $this->getMock('Predis\Network\IConnectionSingle'); + $connection2->expects($this->once()) + ->method('executeCommand') + ->with($ping) + ->will($this->returnValue(false)); + + $client = new Client(array($connection1, $connection2)); + + $this->assertSame(array(true, false), $client->executeCommandOnShards($ping)); + } + + /** + * @group disconnected + */ + public function testExecuteCommandOnEachNodeButConnectionSingle() + { + $ping = ServerProfile::getDefault()->createCommand('ping', array()); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once()) + ->method('executeCommand') + ->with($ping) + ->will($this->returnValue(true)); + + $client = new Client($connection); + + $this->assertSame(array(true), $client->executeCommandOnShards($ping)); + } + + /** + * @group disconnected + */ + public function testCallingRedisCommandExecutesInstanceOfCommand() + { + $ping = ServerProfile::getDefault()->createCommand('ping', array()); + + $connection = $this->getMock('Predis\Network\IConnection'); + $connection->expects($this->once()) + ->method('executeCommand') + ->with($this->isInstanceOf('Predis\Commands\ConnectionPing')) + ->will($this->returnValue(true)); + + $profile = $this->getMock('Predis\Profiles\IServerProfile'); + $profile->expects($this->once()) + ->method('createCommand') + ->with('ping', array()) + ->will($this->returnValue($ping)); + + $client = $this->getMock('Predis\Client', array('createCommand'), array($connection, $profile)); + + $this->assertTrue($client->ping()); + } + + /** + * @group disconnected + * @expectedException Predis\ClientException + * @expectedExceptionMessage 'invalidcommand' is not a registered Redis command + */ + public function testThrowsExceptionOnNonRegisteredRedisCommand() + { + $client = new Client(); + $client->invalidCommand(); + } + + /** + * @group disconnected + */ + public function testGetConnectionFromClusterWithAlias() + { + $client = new Client(array('tcp://host1?alias=node01', 'tcp://host2?alias=node02')); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $cluster = $client->getConnection()); + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $node01 = $client->getConnection('node01')); + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $node02 = $client->getConnection('node02')); + + $this->assertSame('host1', $node01->getParameters()->host); + $this->assertSame('host2', $node02->getParameters()->host); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage Retrieving connections by alias is supported only with clustered connections + */ + public function testGetConnectionWithAliasWorksOnlyWithCluster() + { + $client = new Client(); + + $client->getConnection('node01'); + } + + /** + * @group disconnected + */ + public function testPipelineWithoutArgumentsReturnsPipelineContext() + { + $client = new Client(); + + $this->assertInstanceOf('Predis\Pipeline\PipelineContext', $pipeline = $client->pipeline()); + } + + /** + * @group disconnected + */ + public function testPipelineWithArrayReturnsPipelineContextWithOptions() + { + $client = new Client(); + + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $options = array('executor' => $executor); + + $this->assertInstanceOf('Predis\Pipeline\PipelineContext', $pipeline = $client->pipeline($options)); + + $reflection = new \ReflectionProperty($pipeline, 'executor'); + $reflection->setAccessible(true); + + $this->assertSame($executor, $reflection->getValue($pipeline)); + } + + /** + * @group disconnected + */ + public function testPipelineWithCallableExecutesPipeline() + { + $callable = $this->getMock('stdClass', array('__invoke')); + $callable->expects($this->once()) + ->method('__invoke') + ->with($this->isInstanceOf('Predis\Pipeline\PipelineContext')); + + $client = new Client(); + $client->pipeline($callable); + } + + /** + * @group disconnected + */ + public function testPipelineWithArrayAndCallableExecutesPipelineWithOptions() + { + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $options = array('executor' => $executor); + + $test = $this; + $mockCallback = function($pipeline) use($executor, $test) { + $reflection = new \ReflectionProperty($pipeline, 'executor'); + $reflection->setAccessible(true); + + $test->assertSame($executor, $reflection->getValue($pipeline)); + }; + + $callable = $this->getMock('stdClass', array('__invoke')); + $callable->expects($this->once()) + ->method('__invoke') + ->with($this->isInstanceOf('Predis\Pipeline\PipelineContext')) + ->will($this->returnCallback($mockCallback)); + + $client = new Client(); + $client->pipeline($options, $callable); + } + + /** + * @group disconnected + */ + public function testPubSubWithoutArgumentsReturnsPubSubContext() + { + $client = new Client(); + + $this->assertInstanceOf('Predis\PubSub\PubSubContext', $pubsub = $client->pubSub()); + } + + /** + * @group disconnected + */ + public function testPubSubWithArrayReturnsPubSubContextWithOptions() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $options = array('subscribe' => 'channel'); + + $client = new Client($connection); + + $this->assertInstanceOf('Predis\PubSub\PubSubContext', $pubsub = $client->pubSub($options)); + + $reflection = new \ReflectionProperty($pubsub, 'options'); + $reflection->setAccessible(true); + + $this->assertSame($options, $reflection->getValue($pubsub)); + } + + /** + * @group disconnected + */ + public function testPubSubWithArrayAndCallableExecutesPubSub() + { + // NOTE: we use a subscribe count of 0 in the fake message to trick + // the context and to make it think that it can be closed + // since there are no more subscriptions active. + + $message = array('subscribe', 'channel', 0); + $options = array('subscribe' => 'channel'); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once()) + ->method('read') + ->will($this->returnValue($message)); + + $callable = $this->getMock('stdClass', array('__invoke')); + $callable->expects($this->once()) + ->method('__invoke'); + + $client = new Client($connection); + $client->pubSub($options, $callable); + } + + /** + * @group disconnected + */ + public function testMultiExecWithoutArgumentsReturnsMultiExecContext() + { + $client = new Client(); + + $this->assertInstanceOf('Predis\Transaction\MultiExecContext', $pubsub = $client->multiExec()); + } + + /** + * @group disconnected + */ + public function testMultiExecWithArrayReturnsMultiExecContextWithOptions() + { + $options = array('cas' => true, 'retry' => 3); + + $client = new Client(); + + $this->assertInstanceOf('Predis\Transaction\MultiExecContext', $tx = $client->multiExec($options)); + + $reflection = new \ReflectionProperty($tx, 'options'); + $reflection->setAccessible(true); + + $this->assertSame($options, $reflection->getValue($tx)); + } + + /** + * @group disconnected + */ + public function testMultiExecWithArrayAndCallableExecutesMultiExec() + { + // NOTE: we use CAS since testing the actual MULTI/EXEC context + // here is not the point. + $options = array('cas' => true, 'retry' => 3); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once()) + ->method('executeCommand') + ->will($this->returnValue(new ResponseQueued())); + + $txCallback = function($tx) { $tx->ping(); }; + + $callable = $this->getMock('stdClass', array('__invoke')); + $callable->expects($this->once()) + ->method('__invoke') + ->will($this->returnCallback($txCallback)); + + $client = new Client($connection); + $client->multiExec($options, $callable); + } + + /** + * @group disconnected + */ + public function testMonitorReturnsMonitorContext() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $client = new Client($connection); + + $this->assertInstanceOf('Predis\MonitorContext', $monitor = $client->monitor()); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a named array with the default connection parameters and their values. + * + * @return Array Default connection parameters. + */ + protected function getDefaultParametersArray() + { + return array( + 'scheme' => 'tcp', + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'database' => REDIS_SERVER_DBNUM, + ); + } + + /** + * Returns a named array with the default client options and their values. + * + * @return Array Default connection parameters. + */ + protected function getDefaultOptionsArray() + { + return array( + 'profile' => REDIS_SERVER_VERSION, + ); + } + + /** + * Returns a named array with the default connection parameters merged with + * the specified additional parameters. + * + * @param Array $additional Additional connection parameters. + * @return Array Connection parameters. + */ + protected function getParametersArray(Array $additional) + { + return array_merge($this->getDefaultParametersArray(), $additional); + } + + /** + * Returns an URI string representation of the specified connection parameters. + * + * @param Array $parameters Array of connection parameters. + * @return String URI string. + */ + protected function getParametersString(Array $parameters) + { + $defaults = $this->getDefaultParametersArray(); + + $scheme = isset($parameters['scheme']) ? $parameters['scheme'] : $defaults['scheme']; + $host = isset($parameters['host']) ? $parameters['host'] : $defaults['host']; + $port = isset($parameters['port']) ? $parameters['port'] : $defaults['port']; + + unset($parameters['scheme'], $parameters['host'], $parameters['port']); + $uriString = "$scheme://$host:$port/?"; + + foreach ($parameters as $k => $v) { + $uriString .= "$k=$v&"; + } + + return $uriString; + } +} diff --git a/tests/Predis/Commands/CommandTest.php b/tests/Predis/Commands/CommandTest.php new file mode 100644 index 00000000..bc141ac6 --- /dev/null +++ b/tests/Predis/Commands/CommandTest.php @@ -0,0 +1,216 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class CommandTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testImplementsCorrectInterface() + { + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + + $this->assertInstanceOf('Predis\Commands\ICommand', $command); + } + + /** + * @group disconnected + */ + public function testGetEmptyArguments() + { + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + + $this->assertEmpty($command->getArguments()); + } + + /** + * @group disconnected + */ + public function testSetRawArguments() + { + $arguments = array('1st', '2nd', '3rd'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setRawArguments($arguments); + + $this->assertEquals($arguments, $command->getArguments()); + } + + /** + * @group disconnected + * + * @todo Since Command::filterArguments is protected we cannot set an expectation + * for it when Command::setArguments() is invoked. I wonder how we can do that. + */ + public function testSetArguments() + { + $arguments = array('1st', '2nd', '3rd'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setArguments($arguments); + + $this->assertEquals($arguments, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testGetArgumentAtIndex() + { + $arguments = array('1st', '2nd', '3rd'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setArguments($arguments); + + $this->assertEquals($arguments[0], $command->getArgument(0)); + $this->assertEquals($arguments[2], $command->getArgument(2)); + $this->assertNull($command->getArgument(10)); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $response = 'response-buffer'; + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + + $this->assertEquals($response, $command->parseResponse($response)); + } + + /** + * @group disconnected + * @protected + */ + public function testCheckSameHashForKeys() + { + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + + $checkSameHashForKeys = new \ReflectionMethod($command, 'checkSameHashForKeys'); + $checkSameHashForKeys->setAccessible(true); + + $this->assertTrue($checkSameHashForKeys->invoke($command, array('foo', '{foo}:bar'))); + $this->assertFalse($checkSameHashForKeys->invoke($command, array('foo', '{foo}:bar', 'foo:bar'))); + } + + /** + * @group disconnected + * @protected + */ + public function testCanBeHashed() + { + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + + $canBeHashed = new \ReflectionMethod($command, 'canBeHashed'); + $canBeHashed->setAccessible(true); + + $this->assertFalse($canBeHashed->invoke($command)); + + $command->setRawArguments(array('key')); + $this->assertTrue($canBeHashed->invoke($command)); + } + + /** + * @group disconnected + */ + public function testDoesNotReturnAnHashByDefault() + { + $distributor = $this->getMock('Predis\Distribution\INodeKeyGenerator'); + $distributor->expects($this->never())->method('generateKey'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + + $command->getHash($distributor); + } + + /** + * @group disconnected + */ + public function testReturnAnHashWhenCanBeHashedAndCachesIt() + { + $key = 'key'; + $hash = "$key-hash"; + + $distributor = $this->getMock('Predis\Distribution\INodeKeyGenerator'); + $distributor->expects($this->once()) + ->method('generateKey') + ->with($key) + ->will($this->returnValue($hash)); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setRawArguments(array($key)); + + $this->assertEquals($hash, $command->getHash($distributor)); + + $this->assertEquals($hash, $command->getHash($distributor)); + $this->assertEquals($hash, $command->getHash($distributor)); + } + + /** + * @group disconnected + */ + public function testExtractsKeyTagsBeforeHashing() + { + $tag = 'key'; + $key = "{{$tag}}:ignore"; + $hash = "$tag-hash"; + + $distributor = $this->getMock('Predis\Distribution\INodeKeyGenerator'); + $distributor->expects($this->once()) + ->method('generateKey') + ->with($tag) + ->will($this->returnValue($hash)); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setRawArguments(array($key)); + + $this->assertEquals($hash, $command->getHash($distributor)); + } + + /** + * @group disconnected + */ + public function testToString() + { + $expected = 'SET key value'; + $arguments = array('key', 'value'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->expects($this->once())->method('getId')->will($this->returnValue('SET')); + + $command->setRawArguments($arguments); + + $this->assertEquals($expected, (string) $command); + } + + /** + * @group disconnected + */ + public function testToStringWithLongArguments() + { + $expected = 'SET key abcdefghijklmnopqrstuvwxyz012345[...]'; + $arguments = array('key', 'abcdefghijklmnopqrstuvwxyz0123456789'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->expects($this->once())->method('getId')->will($this->returnValue('SET')); + + $command->setRawArguments($arguments); + + $this->assertEquals($expected, (string) $command); + } +} diff --git a/tests/Predis/Commands/ConnectionAuthTest.php b/tests/Predis/Commands/ConnectionAuthTest.php new file mode 100644 index 00000000..fdc10f7e --- /dev/null +++ b/tests/Predis/Commands/ConnectionAuthTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-connection + */ +class ConnectionAuthTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ConnectionAuth'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'AUTH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('password'); + $expected = array('password'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = null; + $expected = null; + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } +} diff --git a/tests/Predis/Commands/ConnectionEchoTest.php b/tests/Predis/Commands/ConnectionEchoTest.php new file mode 100644 index 00000000..8a61949f --- /dev/null +++ b/tests/Predis/Commands/ConnectionEchoTest.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-connection + */ +class ConnectionEchoTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ConnectionEcho'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ECHO'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('message'); + $expected = array('message'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = 'message'; + $expected = 'message'; + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group connected + */ + public function testAlwaysReturnsThePassedMessage() + { + $redis = $this->getClient(); + + $message = 'Can you hear me?'; + + $this->assertSame($message, $redis->echo($message)); + } +} diff --git a/tests/Predis/Commands/ConnectionPingTest.php b/tests/Predis/Commands/ConnectionPingTest.php new file mode 100644 index 00000000..6f2f0462 --- /dev/null +++ b/tests/Predis/Commands/ConnectionPingTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-connection + */ +class ConnectionPingTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ConnectionPing'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PING'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array(); + $expected = array(); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse('PONG')); + } + + /** + * @group connected + */ + public function testAlwaysReturnsTrue() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->ping()); + } +} diff --git a/tests/Predis/Commands/ConnectionQuitTest.php b/tests/Predis/Commands/ConnectionQuitTest.php new file mode 100644 index 00000000..90a0032e --- /dev/null +++ b/tests/Predis/Commands/ConnectionQuitTest.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-connection + */ +class ConnectionQuitTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ConnectionQuit'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'QUIT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array(); + $expected = array(); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(true)); + } + + /** + * @group connected + */ + public function testReturnsTrueWhenClosingConnection() + { + $redis = $this->getClient(); + $command = $this->getCommand(); + + $this->assertTrue($redis->executeCommand($command)); + } +} diff --git a/tests/Predis/Commands/ConnectionSelectTest.php b/tests/Predis/Commands/ConnectionSelectTest.php new file mode 100644 index 00000000..da3a5254 --- /dev/null +++ b/tests/Predis/Commands/ConnectionSelectTest.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-connection + */ +class ConnectionSelectTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ConnectionSelect'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SELECT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array(10); + $expected = array(10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(true)); + } + + /** + * @group connected + */ + public function testCanSelectDifferentDatabase() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->select(REDIS_SERVER_DBNUM - 1)); + $this->assertFalse($redis->exists('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR invalid DB index + */ + public function testThrowsExceptionOnUnexpectedDatabase() + { + $redis = $this->getClient(); + + $redis->select(100000000); + } +} diff --git a/tests/Predis/Commands/HashDeleteTest.php b/tests/Predis/Commands/HashDeleteTest.php new file mode 100644 index 00000000..ba713e5a --- /dev/null +++ b/tests/Predis/Commands/HashDeleteTest.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashDeleteTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashDelete'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HDEL'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field1', 'field2', 'field3'); + $expected = array('key', 'field1', 'field2', 'field3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsFieldsAsSingleArray() + { + $arguments = array('key', array('field1', 'field2', 'field3')); + $expected = array('key', 'field1', 'field2', 'field3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field1', 'field2', 'field3'); + $expected = array('prefix:key', 'field1', 'field2', 'field3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testDeletesSpecifiedFieldsFromHash() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + + $this->assertSame(2, $redis->hdel('metavars', 'foo', 'hoge')); + $this->assertSame(0, $redis->hdel('metavars', 'foofoo')); + $this->assertSame(0, $redis->hdel('unknown', 'foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hdel('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/HashExistsTest.php b/tests/Predis/Commands/HashExistsTest.php new file mode 100644 index 00000000..011811ae --- /dev/null +++ b/tests/Predis/Commands/HashExistsTest.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashExistsTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashExists'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HEXISTS'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field'); + $expected = array('key', 'field'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertFalse($command->parseResponse(0)); + $this->assertTrue($command->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field'); + $expected = array('prefix:key', 'field'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsExistenceOfSpecifiedField() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo'); + + $this->assertTrue($redis->hexists('metavars', 'foo')); + $this->assertFalse($redis->hexists('metavars', 'lol')); + $this->assertFalse($redis->hexists('unknown', 'foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hexists('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/HashGetAllTest.php b/tests/Predis/Commands/HashGetAllTest.php new file mode 100644 index 00000000..5c4ad294 --- /dev/null +++ b/tests/Predis/Commands/HashGetAllTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashGetAllTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashGetAll'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HGETALL'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + $expected = array('foo' => 'bar', 'hoge' => 'piyo', 'lol' => 'wut'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsAllTheFieldsAndTheirValues() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + + $this->assertSame(array('foo' => 'bar', 'hoge' => 'piyo', 'lol' => 'wut'), $redis->hgetall('metavars')); + $this->assertSame(array(), $redis->hgetall('unknown')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hgetall('foo'); + } +} diff --git a/tests/Predis/Commands/HashGetMultipleTest.php b/tests/Predis/Commands/HashGetMultipleTest.php new file mode 100644 index 00000000..6a8b848b --- /dev/null +++ b/tests/Predis/Commands/HashGetMultipleTest.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashGetMultipleTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashGetMultiple'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HMGET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field1', 'field2', 'field3'); + $expected = array('key', 'field1', 'field2', 'field3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsFieldsAsSingleArray() + { + $arguments = array('key', array('field1', 'field2', 'field3')); + $expected = array('key', 'field1', 'field2', 'field3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('bar', 'piyo', 'wut'); + $expected = array('bar', 'piyo', 'wut'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field1', 'field2', 'field3'); + $expected = array('prefix:key', 'field1', 'field2', 'field3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsValuesOfSpecifiedFields() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + + $this->assertSame(array('bar', 'piyo', null), $redis->hmget('metavars', 'foo', 'hoge', 'unknown')); + $this->assertSame(array('bar', 'bar'), $redis->hmget('metavars', 'foo', 'foo')); + $this->assertSame(array(null, null), $redis->hmget('metavars', 'unknown', 'unknown')); + $this->assertSame(array(null, null), $redis->hmget('unknown', 'foo', 'hoge')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hmget('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/HashGetTest.php b/tests/Predis/Commands/HashGetTest.php new file mode 100644 index 00000000..9abc8587 --- /dev/null +++ b/tests/Predis/Commands/HashGetTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashGetTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashGet'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HGET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field'); + $expected = array('key', 'field'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('value', $this->getCommand()->parseResponse('value')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field'); + $expected = array('prefix:key', 'field'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsValueOfSpecifiedField() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo'); + + $this->assertSame('bar', $redis->hget('metavars', 'foo')); + $this->assertNull($redis->hget('metavars', 'lol')); + $this->assertNull($redis->hget('unknown', 'foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hget('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/HashIncrementByFloatTest.php b/tests/Predis/Commands/HashIncrementByFloatTest.php new file mode 100644 index 00000000..36659953 --- /dev/null +++ b/tests/Predis/Commands/HashIncrementByFloatTest.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashIncrementByFloatTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashIncrementByFloat'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HINCRBYFLOAT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field', 10.5); + $expected = array('key', 'field', 10.5); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(10.5, $this->getCommand()->parseResponse(10.5)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field', 10.5); + $expected = array('prefix:key', 'field', 10.5); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testIncrementsValueOfFieldByFloat() + { + $redis = $this->getClient(); + + $this->assertSame('10.5', $redis->hincrbyfloat('metavars', 'foo', 10.5)); + $this->assertSame('10.001', $redis->hincrbyfloat('metavars', 'hoge', 10.001)); + $this->assertSame('11', $redis->hincrbyfloat('metavars', 'hoge', 0.999)); + $this->assertSame(array('foo' => '10.5', 'hoge' => '11'), $redis->hgetall('metavars')); + } + + /** + * @group connected + */ + public function testDecrementsValueOfFieldByFloat() + { + $redis = $this->getClient(); + + $this->assertSame('-10.5', $redis->hincrbyfloat('metavars', 'foo', -10.5)); + $this->assertSame('-10.001', $redis->hincrbyfloat('metavars', 'hoge', -10.001)); + $this->assertSame('-11', $redis->hincrbyfloat('metavars', 'hoge', -0.999)); + $this->assertSame(array('foo' => '-10.5', 'hoge' => '-11'), $redis->hgetall('metavars')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR hash value is not a valid float + */ + public function testThrowsExceptionOnStringField() + { + $redis = $this->getClient(); + + $redis->hset('metavars', 'foo', 'bar'); + $redis->hincrbyfloat('metavars', 'foo', 10.0); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hincrbyfloat('foo', 'bar', 10.5); + } +} diff --git a/tests/Predis/Commands/HashIncrementByTest.php b/tests/Predis/Commands/HashIncrementByTest.php new file mode 100644 index 00000000..327fa3eb --- /dev/null +++ b/tests/Predis/Commands/HashIncrementByTest.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashIncrementByTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashIncrementBy'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HINCRBY'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field', 10); + $expected = array('key', 'field', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(10, $this->getCommand()->parseResponse(10)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field', 10); + $expected = array('prefix:key', 'field', 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testIncrementsValueOfFieldByInteger() + { + $redis = $this->getClient(); + + $this->assertSame(10, $redis->hincrby('metavars', 'foo', 10)); + $this->assertSame(5, $redis->hincrby('metavars', 'hoge', 5)); + $this->assertSame(15, $redis->hincrby('metavars', 'hoge', 10)); + $this->assertSame(array('foo' => '10', 'hoge' => '15'), $redis->hgetall('metavars')); + } + + /** + * @group connected + */ + public function testDecrementsValueOfFieldByInteger() + { + $redis = $this->getClient(); + + $this->assertSame(-10, $redis->hincrby('metavars', 'foo', -10)); + $this->assertSame(-5, $redis->hincrby('metavars', 'hoge', -5)); + $this->assertSame(-15, $redis->hincrby('metavars', 'hoge', -10)); + $this->assertSame(array('foo' => '-10', 'hoge' => '-15'), $redis->hgetall('metavars')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR hash value is not an integer + */ + public function testThrowsExceptionOnStringField() + { + $redis = $this->getClient(); + + $redis->hset('metavars', 'foo', 'bar'); + $redis->hincrby('metavars', 'foo', 10); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hincrby('foo', 'bar', 10); + } +} diff --git a/tests/Predis/Commands/HashKeysTest.php b/tests/Predis/Commands/HashKeysTest.php new file mode 100644 index 00000000..46d58b1f --- /dev/null +++ b/tests/Predis/Commands/HashKeysTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashKeysTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashKeys'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HKEYS'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('foo', 'hoge', 'lol'); + $expected = array('foo', 'hoge', 'lol'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsKeysOfHash() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + + $this->assertSame(array('foo', 'hoge', 'lol'), $redis->hkeys('metavars')); + $this->assertSame(array(), $redis->hkeys('unknown')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hkeys('foo'); + } +} diff --git a/tests/Predis/Commands/HashLengthTest.php b/tests/Predis/Commands/HashLengthTest.php new file mode 100644 index 00000000..444ecf94 --- /dev/null +++ b/tests/Predis/Commands/HashLengthTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashLengthTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashLength'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HLEN'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsLengthOfHash() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + + $this->assertSame(3, $redis->hlen('metavars')); + $this->assertSame(0, $redis->hlen('unknown')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hlen('foo'); + } +} diff --git a/tests/Predis/Commands/HashSetMultipleTest.php b/tests/Predis/Commands/HashSetMultipleTest.php new file mode 100644 index 00000000..14fcb19c --- /dev/null +++ b/tests/Predis/Commands/HashSetMultipleTest.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashSetMultipleTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashSetMultiple'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HMSET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field1', 'value1', 'field2', 'value2'); + $expected = array('key', 'field1', 'value1', 'field2', 'value2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsFieldsValuesAsSingleArray() + { + $arguments = array('key', array('field1' => 'value1', 'field2' => 'value2')); + $expected = array('key', 'field1', 'value1', 'field2', 'value2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field1', 'value1', 'field2', 'value2'); + $expected = array('prefix:key', 'field1', 'value1', 'field2', 'value2'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testSetsSpecifiedFieldsOfHash() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo')); + $this->assertSame(array('foo' => 'bar', 'hoge' => 'piyo'), $redis->hgetall('metavars')); + + $this->assertTrue($redis->hmset('metavars', 'foo', 'barbar', 'lol', 'wut')); + $this->assertSame(array('foo' => 'barbar', 'hoge' => 'piyo', 'lol' => 'wut'), $redis->hgetall('metavars')); + } + + /** + * @group connected + */ + public function testSetsTheSpecifiedFie() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + + $this->assertSame(array('foo' => 'bar', 'hoge' => 'piyo', 'lol' => 'wut'), $redis->hgetall('metavars')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'bar'); + $redis->hmset('metavars', 'foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/HashSetPreserveTest.php b/tests/Predis/Commands/HashSetPreserveTest.php new file mode 100644 index 00000000..a6a51a05 --- /dev/null +++ b/tests/Predis/Commands/HashSetPreserveTest.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashSetPreserveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashSetPreserve'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HSETNX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field', 'value'); + $expected = array('key', 'field', 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field', 'value'); + $expected = array('prefix:key', 'field', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testSetsNewFieldsAndPreserversExistingOnes() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->hsetnx('metavars', 'foo', 'bar')); + $this->assertTrue($redis->hsetnx('metavars', 'hoge', 'piyo')); + $this->assertFalse($redis->hsetnx('metavars', 'foo', 'barbar')); + + $this->assertSame(array('bar', 'piyo'), $redis->hmget('metavars', 'foo', 'hoge')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->hsetnx('metavars', 'foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/HashSetTest.php b/tests/Predis/Commands/HashSetTest.php new file mode 100644 index 00000000..a2448a10 --- /dev/null +++ b/tests/Predis/Commands/HashSetTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashSetTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashSet'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HSET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'field', 'value'); + $expected = array('key', 'field', 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'field', 'value'); + $expected = array('prefix:key', 'field', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testSetsValueOfSpecifiedField() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->hset('metavars', 'foo', 'bar')); + $this->assertTrue($redis->hset('metavars', 'hoge', 'piyo')); + + $this->assertSame(array('bar', 'piyo'), $redis->hmget('metavars', 'foo', 'hoge')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->hset('metavars', 'foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/HashValuesTest.php b/tests/Predis/Commands/HashValuesTest.php new file mode 100644 index 00000000..853993e1 --- /dev/null +++ b/tests/Predis/Commands/HashValuesTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-hash + */ +class HashValuesTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\HashValues'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'HVALS'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('foo', 'hoge', 'lol'); + $expected = array('foo', 'hoge', 'lol'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsValuesOfHash() + { + $redis = $this->getClient(); + + $redis->hmset('metavars', 'foo', 'bar', 'hoge', 'piyo', 'lol', 'wut'); + + $this->assertSame(array('bar', 'piyo', 'wut'), $redis->hvals('metavars')); + $this->assertSame(array(), $redis->hvals('unknown')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->hvals('foo'); + } +} diff --git a/tests/Predis/Commands/KeyDeleteTest.php b/tests/Predis/Commands/KeyDeleteTest.php new file mode 100644 index 00000000..d33663a6 --- /dev/null +++ b/tests/Predis/Commands/KeyDeleteTest.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyDeleteTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyDelete'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'DEL'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3')); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertSame(10, $command->parseResponse(10)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsNumberOfDeletedKeys() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->del('foo')); + + $redis->set('foo', 'bar'); + $this->assertSame(1, $redis->del('foo')); + + $redis->set('foo', 'bar'); + $this->assertSame(1, $redis->del('foo', 'hoge')); + + $redis->set('foo', 'bar'); + $redis->set('hoge', 'piyo'); + $this->assertSame(2, $redis->del('foo', 'hoge')); + } +} diff --git a/tests/Predis/Commands/KeyExistsTest.php b/tests/Predis/Commands/KeyExistsTest.php new file mode 100644 index 00000000..21cb68bc --- /dev/null +++ b/tests/Predis/Commands/KeyExistsTest.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyExistsTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyExists'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'EXISTS'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsTrueIfKeyExists() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $this->assertTrue($redis->exists('foo')); + } + + /** + * @group connected + */ + public function testReturnsFalseIfKeyDoesNotExist() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->exists('foo')); + } +} diff --git a/tests/Predis/Commands/KeyExpireAtTest.php b/tests/Predis/Commands/KeyExpireAtTest.php new file mode 100644 index 00000000..9a93a884 --- /dev/null +++ b/tests/Predis/Commands/KeyExpireAtTest.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyExpireAtTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyExpireAt'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'EXPIREAT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'ttl'); + $expected = array('key', 'ttl'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->expireat('foo', 2)); + } + + /** + * @group connected + * @group slow + */ + public function testCanExpireKeys() + { + $redis = $this->getClient(); + + $now = time(); + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->expireat('foo', $now + 1)); + $this->assertLessThanOrEqual(1, $redis->ttl('foo')); + + $this->sleep(2); + + $this->assertFalse($redis->exists('foo')); + } + + /** + * @group connected + */ + public function testDeletesKeysOnPastUnixTime() + { + $redis = $this->getClient(); + + $now = time(); + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->expireat('foo', $now - 100)); + $this->assertFalse($redis->exists('foo')); + } +} diff --git a/tests/Predis/Commands/KeyExpireTest.php b/tests/Predis/Commands/KeyExpireTest.php new file mode 100644 index 00000000..6b472282 --- /dev/null +++ b/tests/Predis/Commands/KeyExpireTest.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyExpireTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyExpire'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'EXPIRE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'ttl'); + $expected = array('key', 'ttl'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->expire('foo', 2)); + } + + /** + * @group connected + * @group slow + */ + public function testCanExpireKeys() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->expire('foo', 1)); + $this->assertSame(1, $redis->ttl('foo')); + + $this->sleep(2.0); + + $this->assertFalse($redis->exists('foo')); + } + + /** + * @group connected + * @group slow + */ + public function testConsistencyWithTTL() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->expire('foo', 10)); + $this->sleep(1.5); + $this->assertLessThan(10, $redis->ttl('foo')); + } + + /** + * @group connected + */ + public function testDeletesKeysOnNegativeTTL() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->expire('foo', -10)); + $this->assertFalse($redis->exists('foo')); + } +} diff --git a/tests/Predis/Commands/KeyKeysTest.php b/tests/Predis/Commands/KeyKeysTest.php new file mode 100644 index 00000000..0ce1c49d --- /dev/null +++ b/tests/Predis/Commands/KeyKeysTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyKeysTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyKeys'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'KEYS'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('pattern:*'); + $expected = array('pattern:*'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('key1', 'key2', 'key3'); + $parsed = array('key1', 'key2', 'key3'); + + $this->assertSame($parsed, $this->getCommand()->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('pattern'); + $expected = array('prefix:pattern'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsArrayOfMatchingKeys() + { + $keys = array('aaa' => 1, 'aba' => 2, 'aca' => 3); + $keysNS = array('metavar:foo' => 'bar', 'metavar:hoge' => 'piyo'); + $keysAll = array_merge($keys, $keysNS); + + $redis = $this->getClient(); + $redis->mset($keysAll); + + $this->assertSame(array(), $redis->keys('nomatch:*')); + $this->assertSameValues(array_keys($keysNS), $redis->keys('metavar:*')); + $this->assertSameValues(array_keys($keysAll), $redis->keys('*')); + $this->assertSameValues(array_keys($keys), $redis->keys('a?a')); + } +} diff --git a/tests/Predis/Commands/KeyKeysV12xTest.php b/tests/Predis/Commands/KeyKeysV12xTest.php new file mode 100644 index 00000000..b29deded --- /dev/null +++ b/tests/Predis/Commands/KeyKeysV12xTest.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * We only perform disconnected tests for this commands because + * it is too old (Redis v1.2) and expects a different response + * format. + * + * @group commands + * @group realm-key + */ +class KeyKeysV12xTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyKeysV12x'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'KEYS'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('pattern:*'); + $expected = array('pattern:*'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = 'key1 key2 key3'; + $parsed = array('key1', 'key2', 'key3'); + + $this->assertSame($parsed, $this->getCommand()->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('pattern'); + $expected = array('prefix:pattern'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } +} diff --git a/tests/Predis/Commands/KeyMoveTest.php b/tests/Predis/Commands/KeyMoveTest.php new file mode 100644 index 00000000..8e6700b0 --- /dev/null +++ b/tests/Predis/Commands/KeyMoveTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyMoveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyMove'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'MOVE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 10); + $expected = array('key', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'db'); + $expected = array('prefix:key', 'db'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + * @todo This test fails if REDIS_SERVER_DBNUM is 0. + */ + public function testMovesKeysToDifferentDatabases() + { + $db = REDIS_SERVER_DBNUM - 1; + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->move('foo', $db)); + $this->assertFalse($redis->exists('foo')); + + $redis->select($db); + $this->assertTrue($redis->exists('foo')); + + $redis->del('foo'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR index out of range + */ + public function testThrowsExceptionOnInvalidDatabases() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $redis->move('foo', 100000000); + } +} diff --git a/tests/Predis/Commands/KeyPersistTest.php b/tests/Predis/Commands/KeyPersistTest.php new file mode 100644 index 00000000..2da3c82d --- /dev/null +++ b/tests/Predis/Commands/KeyPersistTest.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyPersistTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyPersist'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PERSIST'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRemovesExpireFromKey() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->expire('foo', 10); + + $this->assertTrue($redis->persist('foo')); + $this->assertSame(-1, $redis->ttl('foo')); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExpiringKeys() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertFalse($redis->persist('foo')); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExistentKeys() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->persist('foo')); + } +} diff --git a/tests/Predis/Commands/KeyPreciseExpireAtTest.php b/tests/Predis/Commands/KeyPreciseExpireAtTest.php new file mode 100644 index 00000000..81b093d3 --- /dev/null +++ b/tests/Predis/Commands/KeyPreciseExpireAtTest.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyPreciseExpireAtTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyPreciseExpireAt'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PEXPIREAT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 100); + $expected = array('key', 100); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + * @group slow + */ + public function testCanExpireKeys() + { + $ttl = 1.5; + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->pexpireat('foo', time() + $ttl * 1000)); + $this->assertLessThan($ttl * 1000, $redis->pttl('foo')); + + $this->sleep($ttl + 0.5); + + $this->assertFalse($redis->exists('foo')); + } + + /** + * @group connected + */ + public function testDeletesKeysOnPastUnixTime() + { + $redis = $this->getClient(); + + $now = time(); + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->expireat('foo', time() - 100000)); + $this->assertFalse($redis->exists('foo')); + } +} diff --git a/tests/Predis/Commands/KeyPreciseExpireTest.php b/tests/Predis/Commands/KeyPreciseExpireTest.php new file mode 100644 index 00000000..0e3ab3cc --- /dev/null +++ b/tests/Predis/Commands/KeyPreciseExpireTest.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyPreciseExpireTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyPreciseExpire'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PEXPIRE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 100); + $expected = array('key', 100); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->pexpire('foo', 20000)); + } + + /** + * @group connected + * @group slow + */ + public function testCanExpireKeys() + { + $ttl = 1 * 1000; + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->pexpire('foo', $ttl)); + + $this->sleep(1.2); + $this->assertFalse($redis->exists('foo')); + } + + /** + * @group connected + * @group slow + */ + public function testConsistencyWithTTL() + { + $ttl = 1 * 1000; + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->pexpire('foo', $ttl)); + + $this->sleep(0.5); + $this->assertLessThanOrEqual($ttl, $redis->pttl('foo')); + $this->assertGreaterThan($ttl - 800, $redis->pttl('foo')); + } + + /** + * @group connected + */ + public function testDeletesKeysOnNegativeTTL() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->pexpire('foo', -10000)); + $this->assertFalse($redis->exists('foo')); + } +} diff --git a/tests/Predis/Commands/KeyPreciseTimeToLiveTest.php b/tests/Predis/Commands/KeyPreciseTimeToLiveTest.php new file mode 100644 index 00000000..4610fb8c --- /dev/null +++ b/tests/Predis/Commands/KeyPreciseTimeToLiveTest.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyPreciseTimeToLiveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyPreciseTimeToLive'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PTTL'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 10); + $expected = array('key', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertSame(100, $command->parseResponse(100)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 10); + $expected = array('prefix:key', 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsTTL() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->expire('foo', 10); + + $this->assertLessThanOrEqual(10000, $redis->pttl('foo')); + } + + /** + * @group connected + */ + public function testReturnsLessThanZeroOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertSame(-1, $redis->pttl('foo')); + } + + /** + * @group connected + */ + public function testReturnsLessThanZeroOnNonExpiringKeys() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $this->assertSame(-1, $redis->pttl('foo')); + } +} diff --git a/tests/Predis/Commands/KeyRandomTest.php b/tests/Predis/Commands/KeyRandomTest.php new file mode 100644 index 00000000..43ebe387 --- /dev/null +++ b/tests/Predis/Commands/KeyRandomTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyRandomTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyRandom'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'RANDOMKEY'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array(); + $expected = array(); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = 'key'; + $expected = 'key'; + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExpiringKeys() + { + $keys = array('key:1' => 1, 'key:2' => 2, 'key:3' => 3); + + $redis = $this->getClient(); + $redis->mset($keys); + + $this->assertContains($redis->randomkey(), array_keys($keys)); + } + + /** + * @group connected + */ + public function testReturnsNullOnEmptyDatabase() + { + $redis = $this->getClient(); + + $this->assertNull($redis->randomkey()); + } +} diff --git a/tests/Predis/Commands/KeyRenamePreserveTest.php b/tests/Predis/Commands/KeyRenamePreserveTest.php new file mode 100644 index 00000000..4f526de6 --- /dev/null +++ b/tests/Predis/Commands/KeyRenamePreserveTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyRenamePreserveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyRenamePreserve'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'RENAMENX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'newkey'); + $expected = array('key', 'newkey'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(1)); + $this->assertFalse($this->getCommand()->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'newkey'); + $expected = array('prefix:key', 'prefix:newkey'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRenamesKeys() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->renamenx('foo', 'foofoo')); + $this->assertFalse($redis->exists('foo')); + $this->assertTrue($redis->exists('foofoo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR no such key + */ + public function testReturnsFalseOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->renamenx('foo', 'foobar')); + } +} diff --git a/tests/Predis/Commands/KeyRenameTest.php b/tests/Predis/Commands/KeyRenameTest.php new file mode 100644 index 00000000..6875f1af --- /dev/null +++ b/tests/Predis/Commands/KeyRenameTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyRenameTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyRename'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'RENAME'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'newkey'); + $expected = array('key', 'newkey'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'newkey'); + $expected = array('prefix:key', 'prefix:newkey'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRenamesKeys() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->rename('foo', 'foofoo')); + $this->assertFalse($redis->exists('foo')); + $this->assertTrue($redis->exists('foofoo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR no such key + */ + public function testThrowsExceptionOnNonExistingKeys() + { + $redis = $this->getClient(); + + $redis->rename('foo', 'foobar'); + } +} diff --git a/tests/Predis/Commands/KeySortTest.php b/tests/Predis/Commands/KeySortTest.php new file mode 100644 index 00000000..69f9c9e1 --- /dev/null +++ b/tests/Predis/Commands/KeySortTest.php @@ -0,0 +1,270 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeySortTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeySort'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SORT'; + } + + /** + * Utility method to to an LPUSH of some unordered values on a key. + * + * @param Predis\Client $redis Redis client instance. + * @param string $key Target key + * @return array + */ + protected function lpushUnorderedList(Predis\Client $redis, $key) + { + $list = array(2, 100, 3, 1, 30, 10); + $redis->lpush($key, $list); + + return $list; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $modifiers = array( + 'by' => 'by_key_*', + 'limit' => array(1, 4), + 'get' => array('object_*', '#'), + 'sort' => 'asc', + 'alpha' => true, + 'store' => 'destination_key', + ); + $arguments = array('key', $modifiers); + + $expected = array( + 'key', 'BY', 'by_key_*', 'GET', 'object_*', 'GET', '#', + 'LIMIT', 1, 4, 'ASC', 'ALPHA', 'STORE', 'destination_key' + ); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertEquals($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testGetModifierCanBeString() + { + $arguments = array('key', array('get' => '#')); + $expected = array('key', 'GET', '#'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('value1', 'value2', 'value3'); + $expected = array('value1', 'value2', 'value3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $modifiers = array( + 'by' => 'by_key_*', + 'limit' => array(1, 4), + 'get' => array('object_*', '#'), + 'sort' => 'asc', + 'alpha' => true, + 'store' => 'destination_key', + ); + $arguments = array('key', $modifiers); + + $expected = array( + 'prefix:key', 'BY', 'prefix:by_key_*', 'GET', 'prefix:object_*', 'GET', '#', + 'LIMIT', 1, 4, 'ASC', 'ALPHA', 'STORE', 'prefix:destination_key' + ); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testBasicSort() + { + $redis = $this->getClient(); + $redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10)); + + $this->assertEquals(array(1, 2, 3, 10, 30, 100), $redis->sort('list:unordered')); + } + + /** + * @group connected + */ + public function testSortWithAscOrDescModifier() + { + $redis = $this->getClient(); + $redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10)); + + $this->assertEquals( + array(100, 30, 10, 3, 2, 1), + $redis->sort('list:unordered', array( + 'sort' => 'desc', + )) + ); + + $this->assertEquals( + array(1, 2, 3, 10, 30, 100), + $redis->sort('list:unordered', array( + 'sort' => 'asc', + )) + ); + } + + /** + * @group connected + */ + public function testSortWithLimitModifier() + { + $redis = $this->getClient(); + $redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10)); + + $this->assertEquals( + array(1, 2, 3), + $redis->sort('list:unordered', array( + 'limit' => array(0, 3), + )) + ); + + $this->assertEquals( + array(10, 30), + $redis->sort('list:unordered', array( + 'limit' => array(3, 2) + )) + ); + } + + /** + * @group connected + */ + public function testSortWithAlphaModifier() + { + $redis = $this->getClient(); + $redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10)); + + $this->assertEquals( + array(1, 10, 100, 2, 3, 30), + $redis->sort('list:unordered', array( + 'alpha' => true + )) + ); + } + + /** + * @group connected + */ + public function testSortWithStoreModifier() + { + $redis = $this->getClient(); + $redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10)); + + $this->assertEquals( + count($unordered), + $redis->sort('list:unordered', array( + 'store' => 'list:ordered' + )) + ); + + $this->assertEquals(array(1, 2, 3, 10, 30, 100), $redis->lrange('list:ordered', 0, -1)); + } + + /** + * @group connected + */ + public function testSortWithCombinedModifiers() + { + $redis = $this->getClient(); + $redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10)); + + $this->assertEquals( + array(30, 10, 3, 2), + $redis->sort('list:unordered', array( + 'alpha' => false, + 'sort' => 'desc', + 'limit' => array(1, 4) + )) + ); + } + + /** + * @group connected + */ + public function testSortWithGetModifiers() + { + $redis = $this->getClient(); + $redis->lpush('list:unordered', $unordered = array(2, 100, 3, 1, 30, 10)); + + $redis->rpush('list:uids', $uids = array(1003, 1001, 1002, 1000)); + $redis->mset($sortget = array( + 'uid:1000' => 'foo', 'uid:1001' => 'bar', + 'uid:1002' => 'hoge', 'uid:1003' => 'piyo', + )); + + $this->assertEquals(array_values($sortget), $redis->sort('list:uids', array('get' => 'uid:*'))); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->sort('foo'); + } +} diff --git a/tests/Predis/Commands/KeyTimeToLiveTest.php b/tests/Predis/Commands/KeyTimeToLiveTest.php new file mode 100644 index 00000000..2aec9a91 --- /dev/null +++ b/tests/Predis/Commands/KeyTimeToLiveTest.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyTimeToLiveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyTimeToLive'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'TTL'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 10); + $expected = array('key', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertSame(100, $command->parseResponse(100)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 10); + $expected = array('prefix:key', 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsTTL() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->expire('foo', 10); + + $this->assertSame(10, $redis->ttl('foo')); + } + + /** + * @group connected + */ + public function testReturnsLessThanZeroOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertSame(-1, $redis->ttl('foo')); + } + + /** + * @group connected + */ + public function testReturnsLessThanZeroOnNonExpiringKeys() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $this->assertSame(-1, $redis->ttl('foo')); + } +} diff --git a/tests/Predis/Commands/KeyTypeTest.php b/tests/Predis/Commands/KeyTypeTest.php new file mode 100644 index 00000000..983a1f51 --- /dev/null +++ b/tests/Predis/Commands/KeyTypeTest.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-key + */ +class KeyTypeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\KeyType'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'TYPE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('type', $this->getCommand()->parseResponse('type')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsTypeOfKey() + { + $redis = $this->getClient(); + + $this->assertSame('none', $redis->type('type:keydoesnotexist')); + + $redis->set('type:string', 'foobar'); + $this->assertSame('string', $redis->type('type:string')); + + $redis->lpush('type:list', 'foobar'); + $this->assertSame('list', $redis->type('type:list')); + + $redis->sadd('type:set', 'foobar'); + $this->assertSame('set', $redis->type('type:set')); + + $redis->zadd('type:zset', 0, 'foobar'); + $this->assertSame('zset', $redis->type('type:zset')); + + $redis->hset('type:hash', 'foo', 'bar'); + $this->assertSame('hash', $redis->type('type:hash')); + } +} diff --git a/tests/Predis/Commands/ListIndexTest.php b/tests/Predis/Commands/ListIndexTest.php new file mode 100644 index 00000000..47fe7993 --- /dev/null +++ b/tests/Predis/Commands/ListIndexTest.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListIndexTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListIndex'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LINDEX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 1); + $expected = array('key', 1); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(0, $this->getCommand()->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 1); + $expected = array('prefix:key', 1); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsElementAtIndex() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e'); + + $this->assertSame('a', $redis->lindex('letters', 0)); + $this->assertSame('c', $redis->lindex('letters', 2)); + $this->assertNull($redis->lindex('letters', 100)); + } + + /** + * @group connected + */ + public function testReturnsElementAtNegativeIndex() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e'); + + $this->assertSame('a', $redis->lindex('letters', -0)); + $this->assertSame('c', $redis->lindex('letters', -3)); + $this->assertSame('e', $redis->lindex('letters', -1)); + $this->assertNull($redis->lindex('letters', -100)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->lindex('foo', 0); + } +} diff --git a/tests/Predis/Commands/ListInsertTest.php b/tests/Predis/Commands/ListInsertTest.php new file mode 100644 index 00000000..2b561b9d --- /dev/null +++ b/tests/Predis/Commands/ListInsertTest.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListInsertTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListInsert'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LINSERT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'before', 'value1', 'value2'); + $expected = array('key', 'before', 'value1', 'value2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'before', 'value1', 'value2'); + $expected = array('prefix:key', 'before', 'value1', 'value2'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsLengthOfListAfterInser() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'c', 'e'); + + $this->assertSame(4, $redis->linsert('letters', 'before', 'c', 'b')); + $this->assertSame(5, $redis->linsert('letters', 'after', 'c', 'd')); + $this->assertSame(array('a', 'b', 'c', 'd', 'e'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testReturnsNegativeLengthOnFailedInsert() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'c', 'e'); + + $this->assertSame(-1, $redis->linsert('letters', 'before', 'n', 'm')); + $this->assertSame(-1, $redis->linsert('letters', 'after', 'o', 'p')); + } + + /** + * @group connected + */ + public function testReturnsZeroLengthOnNonExistingList() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->linsert('letters', 'after', 'a', 'b')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->linsert('foo', 'BEFORE', 'bar', 'baz'); + } +} diff --git a/tests/Predis/Commands/ListLengthTest.php b/tests/Predis/Commands/ListLengthTest.php new file mode 100644 index 00000000..ab29d1c2 --- /dev/null +++ b/tests/Predis/Commands/ListLengthTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListLengthTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListLength'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LLEN'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsLengthOfList() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c'); + $this->assertSame(3, $redis->llen('letters')); + + $redis->rpush('letters', 'd', 'e', 'f'); + $this->assertSame(6, $redis->llen('letters')); + } + + /** + * @group connected + */ + public function testReturnsZeroLengthOnNonExistingList() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->llen('letters')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->llen('foo'); + } +} diff --git a/tests/Predis/Commands/ListPopFirstBlockingTest.php b/tests/Predis/Commands/ListPopFirstBlockingTest.php new file mode 100644 index 00000000..2bdb0f19 --- /dev/null +++ b/tests/Predis/Commands/ListPopFirstBlockingTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + * @todo Testing blocking pop operations against Redis using PHP is + * tricky, so we will skip these kind of tests for now. + */ +class ListPopFirstBlockingTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPopFirstBlocking'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'BLPOP'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3', 10); + $expected = array('key1', 'key2', 'key3', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsKeysAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3'), 10); + $expected = array('key1', 'key2', 'key3', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('key', 'value'); + $expected = array('key', 'value'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3', 10); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3', 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } +} diff --git a/tests/Predis/Commands/ListPopFirstTest.php b/tests/Predis/Commands/ListPopFirstTest.php new file mode 100644 index 00000000..64d3c38a --- /dev/null +++ b/tests/Predis/Commands/ListPopFirstTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListPopFirstTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPopFirst'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LPOP'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('element', $this->getCommand()->parseResponse('element')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPopsTheFirstElementFromList() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd'); + + $this->assertSame('a', $redis->lpop('letters')); + $this->assertSame('b', $redis->lpop('letters')); + $this->assertSame(array('c', 'd'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testReturnsNullOnEmptyList() + { + $redis = $this->getClient(); + + $this->assertNull($redis->lpop('letters')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->lpop('foo'); + } +} diff --git a/tests/Predis/Commands/ListPopLastBlockingTest.php b/tests/Predis/Commands/ListPopLastBlockingTest.php new file mode 100644 index 00000000..d7bd6093 --- /dev/null +++ b/tests/Predis/Commands/ListPopLastBlockingTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + * @todo Testing blocking pop operations against Redis using PHP is + * tricky, so we will skip these kind of tests for now. + */ +class ListPopLastBlockingTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPopLastBlocking'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'BRPOP'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3', 10); + $expected = array('key1', 'key2', 'key3', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsKeysAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3'), 10); + $expected = array('key1', 'key2', 'key3', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('key', 'value'); + $expected = array('key', 'value'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3', 10); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3', 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } +} diff --git a/tests/Predis/Commands/ListPopLastPushHeadBlockingTest.php b/tests/Predis/Commands/ListPopLastPushHeadBlockingTest.php new file mode 100644 index 00000000..d009ae9b --- /dev/null +++ b/tests/Predis/Commands/ListPopLastPushHeadBlockingTest.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + * @todo Testing blocking pop operations against Redis using PHP is + * tricky, so we will skip these kind of tests for now. + */ +class ListPopLastPushHeadBlockingTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPopLastPushHeadBlocking'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'BRPOPLPUSH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key:source', 'key:destination', 10); + $expected = array('key:source', 'key:destination', 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('element', $this->getCommand()->parseResponse('element')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key:source', 'key:destination', 10); + $expected = array('prefix:key:source', 'prefix:key:destination', 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } +} diff --git a/tests/Predis/Commands/ListPopLastPushHeadTest.php b/tests/Predis/Commands/ListPopLastPushHeadTest.php new file mode 100644 index 00000000..3b0df6b0 --- /dev/null +++ b/tests/Predis/Commands/ListPopLastPushHeadTest.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListPopLastPushHeadTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPopLastPushHead'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'RPOPLPUSH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key:source', 'key:destination'); + $expected = array('key:source', 'key:destination'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('element', $this->getCommand()->parseResponse('element')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key:source', 'key:destination'); + $expected = array('prefix:key:source', 'prefix:key:destination'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsElementPoppedFromSourceAndPushesToDestination() + { + $redis = $this->getClient(); + + $redis->rpush('letters:source', 'a', 'b', 'c'); + + $this->assertSame('c', $redis->rpoplpush('letters:source', 'letters:destination')); + $this->assertSame('b', $redis->rpoplpush('letters:source', 'letters:destination')); + $this->assertSame('a', $redis->rpoplpush('letters:source', 'letters:destination')); + + $this->assertSame(array(), $redis->lrange('letters:source', 0, -1)); + $this->assertSame(array('a', 'b', 'c'), $redis->lrange('letters:destination', 0, -1)); + } + + /** + * @group connected + */ + public function testReturnsElementPoppedFromSourceAndPushesToSelf() + { + $redis = $this->getClient(); + + $redis->rpush('letters:source', 'a', 'b', 'c'); + + $this->assertSame('c', $redis->rpoplpush('letters:source', 'letters:source')); + $this->assertSame('b', $redis->rpoplpush('letters:source', 'letters:source')); + $this->assertSame('a', $redis->rpoplpush('letters:source', 'letters:source')); + + $this->assertSame(array('a', 'b', 'c'), $redis->lrange('letters:source', 0, -1)); + } + + /** + * @group connected + */ + public function testReturnsNullOnEmptySource() + { + $redis = $this->getClient(); + + $this->assertNull($redis->rpoplpush('key:source', 'key:destination')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongTypeOfSourceKey() + { + $redis = $this->getClient(); + + $redis->set('key:source', 'foo'); + $redis->rpoplpush('key:source', 'key:destination'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongTypeOfDestinationKey() + { + $redis = $this->getClient(); + + $redis->rpush('key:source', 'foo'); + $redis->set('key:destination', 'bar'); + + $redis->rpoplpush('key:source', 'key:destination'); + } +} diff --git a/tests/Predis/Commands/ListPopLastTest.php b/tests/Predis/Commands/ListPopLastTest.php new file mode 100644 index 00000000..79e9252c --- /dev/null +++ b/tests/Predis/Commands/ListPopLastTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListPopLastTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPopLast'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'RPOP'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('element', $this->getCommand()->parseResponse('element')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPopsTheLastElementFromList() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd'); + + $this->assertSame('d', $redis->rpop('letters')); + $this->assertSame('c', $redis->rpop('letters')); + $this->assertSame(array('a', 'b'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testReturnsNullOnEmptyList() + { + $redis = $this->getClient(); + + $this->assertNull($redis->rpop('letters')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->rpop('foo'); + } +} diff --git a/tests/Predis/Commands/ListPushHeadTest.php b/tests/Predis/Commands/ListPushHeadTest.php new file mode 100644 index 00000000..95dc5c2c --- /dev/null +++ b/tests/Predis/Commands/ListPushHeadTest.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListPushHeadTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPushHead'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LPUSH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'value1', 'value2', 'value3'); + $expected = array('key', 'value1', 'value2', 'value3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsValuesAsSingleArray() + { + $arguments = array('key', array('value1', 'value2', 'value3')); + $expected = array('key', 'value1', 'value2', 'value3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value1', 'value2', 'value3'); + $expected = array('prefix:key', 'value1', 'value2', 'value3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPushesElementsToHeadOfList() + { + $redis = $this->getClient(); + + // NOTE: List push operations return the list length since Redis commit 520b5a3 + $this->assertSame(1, $redis->lpush('metavars', 'foo')); + $this->assertSame(2, $redis->lpush('metavars', 'hoge')); + $this->assertSame(array('hoge', 'foo'), $redis->lrange('metavars', 0, -1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->lpush('metavars', 'hoge'); + } +} diff --git a/tests/Predis/Commands/ListPushHeadXTest.php b/tests/Predis/Commands/ListPushHeadXTest.php new file mode 100644 index 00000000..af1db985 --- /dev/null +++ b/tests/Predis/Commands/ListPushHeadXTest.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListPushHeadXTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPushHeadX'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LPUSHX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'value'); + $expected = array('key', 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPushesElementsToHeadOfExistingList() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + + $this->assertSame(2, $redis->lpushx('metavars', 'hoge')); + $this->assertSame(array('hoge', 'foo'), $redis->lrange('metavars', 0, -1)); + } + + /** + * @group connected + */ + public function testDoesNotPushElementOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->lpushx('metavars', 'foo')); + $this->assertSame(0, $redis->lpushx('metavars', 'hoge')); + $this->assertFalse($redis->exists('metavars')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->lpushx('metavars', 'hoge'); + } +} diff --git a/tests/Predis/Commands/ListPushTailTest.php b/tests/Predis/Commands/ListPushTailTest.php new file mode 100644 index 00000000..7011f8cc --- /dev/null +++ b/tests/Predis/Commands/ListPushTailTest.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListPushTailTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPushTail'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'RPUSH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'value1', 'value2', 'value3'); + $expected = array('key', 'value1', 'value2', 'value3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsValuesAsSingleArray() + { + $arguments = array('key', array('value1', 'value2', 'value3')); + $expected = array('key', 'value1', 'value2', 'value3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value1', 'value2', 'value3'); + $expected = array('prefix:key', 'value1', 'value2', 'value3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPushesElementsToHeadOfList() + { + $redis = $this->getClient(); + + // NOTE: List push operations return the list length since Redis commit 520b5a3 + $this->assertSame(1, $redis->rpush('metavars', 'foo')); + $this->assertSame(2, $redis->rpush('metavars', 'hoge')); + $this->assertSame(array('foo', 'hoge'), $redis->lrange('metavars', 0, -1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->rpush('metavars', 'hoge'); + } +} diff --git a/tests/Predis/Commands/ListPushTailXTest.php b/tests/Predis/Commands/ListPushTailXTest.php new file mode 100644 index 00000000..fa8b5f8d --- /dev/null +++ b/tests/Predis/Commands/ListPushTailXTest.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListPushTailXTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListPushTailX'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'RPUSHX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'value'); + $expected = array('key', 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPushesElementsToHeadOfExistingList() + { + $redis = $this->getClient(); + + $redis->rpush('metavars', 'foo'); + + $this->assertSame(2, $redis->rpushx('metavars', 'hoge')); + $this->assertSame(array('foo', 'hoge'), $redis->lrange('metavars', 0, -1)); + } + + /** + * @group connected + */ + public function testDoesNotPushElementOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->rpushx('metavars', 'foo')); + $this->assertSame(0, $redis->rpushx('metavars', 'hoge')); + $this->assertFalse($redis->exists('metavars')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->rpushx('metavars', 'hoge'); + } +} diff --git a/tests/Predis/Commands/ListRangeTest.php b/tests/Predis/Commands/ListRangeTest.php new file mode 100644 index 00000000..2309af83 --- /dev/null +++ b/tests/Predis/Commands/ListRangeTest.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListRangeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListRange'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LRANGE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 0, -1); + $expected = array('key', 0, -1); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('value1', 'value2', 'value3'); + $expected = array('value1', 'value2', 'value3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 0, -1); + $expected = array('prefix:key', 0, -1); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsListSliceWithPositiveStartAndStop() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertSame(array('a', 'b', 'c', 'd'), $redis->lrange('letters', 0, 3)); + $this->assertSame(array('e', 'f', 'g', 'h'), $redis->lrange('letters', 4, 7)); + $this->assertSame(array('a', 'b'), $redis->lrange('letters', 0, 1)); + $this->assertSame(array('a'), $redis->lrange('letters', 0, 0)); + } + + /** + * @group connected + */ + public function testReturnsListSliceWithPositiveStartAndNegativeStop() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertSame(array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'), $redis->lrange('letters', 0, -1)); + $this->assertSame(array('f'), $redis->lrange('letters', 5, -5)); + $this->assertSame(array(), $redis->lrange('letters', 7, -5)); + } + + /** + * @group connected + */ + public function testReturnsListSliceWithNegativeStartAndStop() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertSame(array('f'), $redis->lrange('letters', -5, -5)); + } + + /** + * @group connected + */ + public function testHandlesStartAndStopOverflow() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertSame(array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'), $redis->lrange('letters', -100, 100)); + } + + /** + * @group connected + */ + public function testReturnsEmptyArrayOnNonExistingList() + { + $redis = $this->getClient(); + + $this->assertSame(array(), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->lrange('metavars', 0, -1); + } +} diff --git a/tests/Predis/Commands/ListRemoveTest.php b/tests/Predis/Commands/ListRemoveTest.php new file mode 100644 index 00000000..e0304983 --- /dev/null +++ b/tests/Predis/Commands/ListRemoveTest.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListRemoveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListRemove'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LREM'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 1, 'value'); + $expected = array('key', 1, 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 1, 'value'); + $expected = array('prefix:key', 1, 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRemovesMatchingElementsFromHeadToTail() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', '_', 'b', '_', 'c', '_', 'd', '_'); + + $this->assertSame(2, $redis->lrem('letters', 2, '_')); + $this->assertSame(array('a', 'b', 'c', '_', 'd', '_'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testRemovesMatchingElementsFromTailToHead() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', '_', 'b', '_', 'c', '_', 'd', '_'); + + $this->assertSame(2, $redis->lrem('letters', -2, '_')); + $this->assertSame(array('a', '_', 'b', '_', 'c', 'd'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testRemovesAllMatchingElements() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', '_', 'b', '_', 'c', '_', 'd', '_'); + + $this->assertSame(4, $redis->lrem('letters', 0, '_')); + $this->assertSame(array('a', 'b', 'c', 'd'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testReturnsZeroOnNonMatchingElementsOrEmptyList() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd'); + + $this->assertSame(0, $redis->lrem('letters', 0, 'z')); + $this->assertSame(0, $redis->lrem('digits', 0, 100)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->lrem('metavars', 0, 0); + } +} diff --git a/tests/Predis/Commands/ListSetTest.php b/tests/Predis/Commands/ListSetTest.php new file mode 100644 index 00000000..0f0fa2cc --- /dev/null +++ b/tests/Predis/Commands/ListSetTest.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListSetTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListSet'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LSET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 0, 'value'); + $expected = array('key', 0, 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 0, 'value'); + $expected = array('prefix:key', 0, 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testSetsElementAtSpecifiedIndex() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c'); + + $this->assertTrue($redis->lset('letters', 1, 'B')); + $this->assertSame(array('a', 'B', 'c'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR index out of range + */ + public function testThrowsExceptionOnIndexOutOfRange() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c'); + $redis->lset('letters', 21, 'z'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->lset('metavars', 0, 'hoge'); + } +} diff --git a/tests/Predis/Commands/ListTrimTest.php b/tests/Predis/Commands/ListTrimTest.php new file mode 100644 index 00000000..d523d214 --- /dev/null +++ b/tests/Predis/Commands/ListTrimTest.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-list + */ +class ListTrimTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ListTrim'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LTRIM'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 0, 1); + $expected = array('key', 0, 1); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 0, 1); + $expected = array('prefix:key', 0, 1); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testTrimsListWithPositiveStartAndStop() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertTrue($redis->ltrim('letters', 0, 2)); + $this->assertSame(array('a', 'b', 'c'), $redis->lrange('letters', 0, -1)); + + $redis->flushdb(); + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertTrue($redis->ltrim('letters', 5, 9)); + $this->assertSame(array('f', 'g', 'h', 'i', 'l'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testTrimsListWithPositiveStartAndNegativeStop() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertTrue($redis->ltrim('letters', 0, -6)); + $this->assertSame(array('a', 'b', 'c', 'd', 'e'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testTrimsListWithNegativeStartAndStop() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertTrue($redis->ltrim('letters', -5, -5)); + $this->assertSame(array('f'), $redis->lrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testHandlesStartAndStopOverflow() + { + $redis = $this->getClient(); + + $redis->rpush('letters', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'); + + $this->assertTrue($redis->ltrim('letters', -100, 100)); + $this->assertSame(array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'), $redis->lrange('letters', -100, 100)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->ltrim('metavars', 0, 1); + } +} diff --git a/tests/Predis/Commands/PrefixHelpersTest.php b/tests/Predis/Commands/PrefixHelpersTest.php new file mode 100644 index 00000000..f5d672a4 --- /dev/null +++ b/tests/Predis/Commands/PrefixHelpersTest.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class PrefixHelpersTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testPrefixFirst() + { + $arguments = array('1st', '2nd', '3rd', '4th'); + $expected = array('prefix:1st', '2nd', '3rd', '4th'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setRawArguments($arguments); + + PrefixHelpers::first($command, 'prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testPrefixAll() + { + $arguments = array('1st', '2nd', '3rd', '4th'); + $expected = array('prefix:1st', 'prefix:2nd', 'prefix:3rd', 'prefix:4th'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setRawArguments($arguments); + + PrefixHelpers::all($command, 'prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testPrefixInterleaved() + { + $arguments = array('1st', '2nd', '3rd', '4th'); + $expected = array('prefix:1st', '2nd', 'prefix:3rd', '4th'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setRawArguments($arguments); + + PrefixHelpers::interleaved($command, 'prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testPrefixSkipLast() + { + $arguments = array('1st', '2nd', '3rd', '4th'); + $expected = array('prefix:1st', 'prefix:2nd', 'prefix:3rd', '4th'); + + $command = $this->getMockForAbstractClass('Predis\Commands\Command'); + $command->setRawArguments($arguments); + + PrefixHelpers::skipLast($command, 'prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } +} diff --git a/tests/Predis/Commands/PrefixableCommandTest.php b/tests/Predis/Commands/PrefixableCommandTest.php new file mode 100644 index 00000000..8c391a9a --- /dev/null +++ b/tests/Predis/Commands/PrefixableCommandTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class PrefixableCommandTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testImplementsCorrectInterface() + { + $command = $this->getMockForAbstractClass('Predis\Commands\PrefixableCommand'); + + $this->assertInstanceOf('Predis\Commands\IPrefixable', $command); + $this->assertInstanceOf('Predis\Commands\ICommand', $command); + } + + /** + * @group disconnected + */ + public function testAddPrefixToFirstArgument() + { + $command = $this->getMockForAbstractClass('Predis\Commands\PrefixableCommand'); + $command->setRawArguments(array('key', 'value')); + $command->prefixKeys('prefix:'); + + $this->assertSame(array('prefix:key', 'value'), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testDoesNotBreakOnEmptyArguments() + { + $command = $this->getMockForAbstractClass('Predis\Commands\PrefixableCommand'); + $command->prefixKeys('prefix:'); + + $this->assertEmpty($command->getArguments()); + } +} diff --git a/tests/Predis/Commands/Processors/KeyPrefixProcessorTest.php b/tests/Predis/Commands/Processors/KeyPrefixProcessorTest.php new file mode 100644 index 00000000..b197500e --- /dev/null +++ b/tests/Predis/Commands/Processors/KeyPrefixProcessorTest.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands\Processors; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class KeyPrefixProcessorTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testConstructorWithPrefix() + { + $prefix = 'prefix:'; + $processor = new KeyPrefixProcessor($prefix); + + $this->assertInstanceOf('Predis\Commands\Processors\ICommandProcessor', $processor); + $this->assertEquals($prefix, $processor->getPrefix()); + } + + /** + * @group disconnected + */ + public function testChangePrefix() + { + $prefix1 = 'prefix:'; + $prefix2 = 'prefix:new:'; + + $processor = new KeyPrefixProcessor($prefix1); + $this->assertEquals($prefix1, $processor->getPrefix()); + + $processor->setPrefix($prefix2); + $this->assertEquals($prefix2, $processor->getPrefix()); + } + + /** + * @group disconnected + */ + public function testProcessPrefixableCommands() + { + $prefix = 'prefix:'; + $unprefixed = 'key'; + $expected = "$prefix$unprefixed"; + + $command = $this->getMock('Predis\Commands\PrefixableCommand'); + $command->expects($this->once()) + ->method('prefixKeys') + ->with($prefix); + + $processor = new KeyPrefixProcessor($prefix); + + $processor->process($command); + } + + /** + * @group disconnected + */ + public function testProcessNotPrefixableCommands() + { + $prefix = 'prefix:'; + $unprefixed = 'key'; + $expected = "$prefix$unprefixed"; + + $command = $this->getMock('Predis\Commands\ICommand'); + $command->expects($this->never())->method('prefixKeys'); + + $processor = new KeyPrefixProcessor($prefix); + + $processor->process($command); + } +} diff --git a/tests/Predis/Commands/Processors/ProcessorChainTest.php b/tests/Predis/Commands/Processors/ProcessorChainTest.php new file mode 100644 index 00000000..39be7dad --- /dev/null +++ b/tests/Predis/Commands/Processors/ProcessorChainTest.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands\Processors; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ProcessorChainTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testConstructor() + { + $chain = new ProcessorChain(); + + $this->assertInstanceOf('Predis\Commands\Processors\ICommandProcessor', $chain); + $this->assertInstanceOf('Predis\Commands\Processors\ICommandProcessorChain', $chain); + $this->assertEmpty($chain->getProcessors()); + } + + /** + * @group disconnected + */ + public function testConstructorWithProcessorsArray() + { + $processors = array( + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + ); + + $chain = new ProcessorChain($processors); + + $this->assertSame($processors, $chain->getProcessors()); + } + + /** + * @group disconnected + */ + public function testCountProcessors() + { + $processors = array( + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + ); + + $chain = new ProcessorChain($processors); + + $this->assertEquals(2, $chain->count()); + } + + /** + * @group disconnected + */ + public function testAddProcessors() + { + $processors = array( + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + ); + + $chain = new ProcessorChain(); + $chain->add($processors[0]); + $chain->add($processors[1]); + + $this->assertSame($processors, $chain->getProcessors()); + } + + /** + * @group disconnected + */ + public function testAddMoreProcessors() + { + $processors1 = array( + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + ); + + $processors2 = array( + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + ); + + $chain = new ProcessorChain($processors1); + $chain->add($processors2[0]); + $chain->add($processors2[1]); + + $this->assertSame(array_merge($processors1, $processors2), $chain->getProcessors()); + } + + /** + * @group disconnected + */ + public function testRemoveProcessors() + { + $processors = array( + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + ); + + $chain = new ProcessorChain($processors); + + $chain->remove($processors[0]); + $this->assertSame(array($processors[1]), $chain->getProcessors()); + + $chain->remove($processors[1]); + $this->assertEmpty($chain->getProcessors()); + } + + /** + * @group disconnected + */ + public function testRemoveProcessorNotInChain() + { + $processor = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + $processors = array( + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + $this->getMock('Predis\Commands\Processors\ICommandProcessor'), + ); + + $chain = new ProcessorChain($processors); + $chain->remove($processor); + + $this->assertSame($processors, $chain->getProcessors()); + } + + /** + * @group disconnected + */ + public function testRemoveProcessorFromEmptyChain() + { + $processor = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + + $chain = new ProcessorChain(); + $this->assertEmpty($chain->getProcessors()); + + $chain->remove($processor); + $this->assertEmpty($chain->getProcessors()); + } + + /** + * @group disconnected + */ + public function testProcessChain() + { + $command = $this->getMock('Predis\Commands\ICommand'); + + $processor1 = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + $processor1->expects($this->once())->method('process')->with($command); + + $processor2 = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + $processor2->expects($this->once())->method('process')->with($command); + + $processors = array($processor1, $processor2); + + $chain = new ProcessorChain($processors); + $chain->process($command); + } +} diff --git a/tests/Predis/Commands/PubSubPublishTest.php b/tests/Predis/Commands/PubSubPublishTest.php new file mode 100644 index 00000000..5d1b02ba --- /dev/null +++ b/tests/Predis/Commands/PubSubPublishTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-pubsub + */ +class PubSubPublishTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\PubSubPublish'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PUBLISH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('channel', 'message'); + $expected = array('channel', 'message'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('channel', 'message'); + $expected = array('prefix:channel', 'message'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPublishesMessagesToChannel() + { + $redis1 = $this->getClient(); + $redis2 = $this->getClient(); + + $redis1->subscribe('channel:foo'); + + $this->assertSame(1, $redis2->publish('channel:foo', 'bar')); + $this->assertSame(0, $redis2->publish('channel:hoge', 'piyo')); + } +} diff --git a/tests/Predis/Commands/PubSubSubscribeByPatternTest.php b/tests/Predis/Commands/PubSubSubscribeByPatternTest.php new file mode 100644 index 00000000..ad3b6a8f --- /dev/null +++ b/tests/Predis/Commands/PubSubSubscribeByPatternTest.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-pubsub + */ +class PubSubSubscribeByPatternTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\PubSubSubscribeByPattern'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PSUBSCRIBE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('channel:foo:*', 'channel:hoge:*'); + $expected = array('channel:foo:*', 'channel:hoge:*'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('channel:foo:*', 'channel:hoge:*')); + $expected = array('channel:foo:*', 'channel:hoge:*'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('psubscribe', 'channel:*', 1); + $expected = array('psubscribe', 'channel:*', 1); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('channel:foo:*', 'channel:hoge:*'); + $expected = array('prefix:channel:foo:*', 'prefix:channel:hoge:*'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsTheFirstPsubscribedChannelDetails() + { + $redis = $this->getClient(); + + $this->assertSame(array('psubscribe', 'channel:*', 1), $redis->psubscribe('channel:*')); + } + + /** + * @group connected + */ + public function testCanSendPsubscribeAfterPsubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('psubscribe', 'channel:foo:*', 1), $redis->psubscribe('channel:foo:*')); + $this->assertSame(array('psubscribe', 'channel:hoge:*', 2), $redis->psubscribe('channel:hoge:*')); + } + + /** + * @group connected + */ + public function testCanSendSubscribeAfterPsubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('psubscribe', 'channel:foo:*', 1), $redis->psubscribe('channel:foo:*')); + $this->assertSame(array('subscribe', 'channel:foo:bar', 2), $redis->subscribe('channel:foo:bar')); + } + + /** + * @group connected + */ + public function testCanSendUnsubscribeAfterPsubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('psubscribe', 'channel:foo:*', 1), $redis->psubscribe('channel:foo:*')); + $this->assertSame(array('psubscribe', 'channel:hoge:*', 2), $redis->psubscribe('channel:hoge:*')); + $this->assertSame(array('unsubscribe', 'channel:foo:bar', 2), $redis->unsubscribe('channel:foo:bar')); + } + + /** + * @group connected + */ + public function testCanSendPunsubscribeAfterPsubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('psubscribe', 'channel:foo:*', 1), $redis->psubscribe('channel:foo:*')); + $this->assertSame(array('psubscribe', 'channel:hoge:*', 2), $redis->psubscribe('channel:hoge:*')); + $this->assertSame(array('punsubscribe', 'channel:*:*', 2), $redis->punsubscribe('channel:*:*')); + } + + /** + * @group connected + */ + public function testCanSendQuitAfterPsubscribe() + { + $redis = $this->getClient(); + $quit = $this->getProfile()->createCommand('quit'); + + $this->assertSame(array('subscribe', 'channel1', 1), $redis->subscribe('channel1')); + $this->assertTrue($redis->executeCommand($quit)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context + */ + public function testCannotSendOtherCommandsAfterPsubscribe() + { + $redis = $this->getClient(); + + $redis->psubscribe('channel:*'); + $redis->set('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/PubSubSubscribeTest.php b/tests/Predis/Commands/PubSubSubscribeTest.php new file mode 100644 index 00000000..c725165f --- /dev/null +++ b/tests/Predis/Commands/PubSubSubscribeTest.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-pubsub + */ +class PubSubSubscribeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\PubSubSubscribe'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SUBSCRIBE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('channel:foo', 'channel:bar'); + $expected = array('channel:foo', 'channel:bar'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('channel:foo', 'channel:bar')); + $expected = array('channel:foo', 'channel:bar'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('subscribe', 'channel', 1); + $expected = array('subscribe', 'channel', 1); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array(array('channel:foo', 'channel:bar')); + $expected = array('prefix:channel:foo', 'prefix:channel:bar'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsTheFirstSubscribedChannelDetails() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel', 1), $redis->subscribe('channel')); + } + + /** + * @group connected + */ + public function testCanSendSubscribeAfterSubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertSame(array('subscribe', 'channel:bar', 2), $redis->subscribe('channel:bar')); + } + + /** + * @group connected + */ + public function testCanSendPsubscribeAfterSubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertSame(array('psubscribe', 'channel:*', 2), $redis->psubscribe('channel:*')); + } + + /** + * @group connected + */ + public function testCanSendUnsubscribeAfterSubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertSame(array('subscribe', 'channel:bar', 2), $redis->subscribe('channel:bar')); + $this->assertSame(array('unsubscribe', 'channel:foo', 1), $redis->unsubscribe('channel:foo')); + } + + /** + * @group connected + */ + public function testCanSendPunsubscribeAfterSubscribe() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertSame(array('subscribe', 'channel:bar', 2), $redis->subscribe('channel:bar')); + $this->assertSame(array('punsubscribe', 'channel:*', 2), $redis->punsubscribe('channel:*')); + } + + /** + * @group connected + */ + public function testCanSendQuitAfterSubscribe() + { + $redis = $this->getClient(); + $quit = $this->getProfile()->createCommand('quit'); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertTrue($redis->executeCommand($quit)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context + */ + public function testCannotSendOtherCommandsAfterSubscribe() + { + $redis = $this->getClient(); + + $redis->subscribe('channel:foo'); + $redis->set('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/PubSubUnsubscribeByPatternTest.php b/tests/Predis/Commands/PubSubUnsubscribeByPatternTest.php new file mode 100644 index 00000000..5531fcc9 --- /dev/null +++ b/tests/Predis/Commands/PubSubUnsubscribeByPatternTest.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-pubsub + */ +class PubSubUnsubscribeByPatternTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\PubSubUnsubscribeByPattern'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PUNSUBSCRIBE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('channel:foo:*', 'channel:bar:*'); + $expected = array('channel:foo:*', 'channel:bar:*'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('channel:foo:*', 'channel:bar:*')); + $expected = array('channel:foo:*', 'channel:bar:*'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('punsubscribe', 'channel:*', 1); + $expected = array('punsubscribe', 'channel:*', 1); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array(array('channel:foo:*', 'channel:bar:*')); + $expected = array('prefix:channel:foo:*', 'prefix:channel:bar:*'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testDoesNotSwitchToSubscribeMode() + { + $redis = $this->getClient(); + + $this->assertSame(array('punsubscribe', 'channel:*', 0), $redis->punsubscribe('channel:*')); + $this->assertSame('echoed', $redis->echo('echoed')); + } + + /** + * @group connected + */ + public function testUnsubscribesFromNotSubscribedChannels() + { + $redis = $this->getClient(); + + $this->assertSame(array('punsubscribe', 'channel:*', 0), $redis->punsubscribe('channel:*')); + } + + /** + * @group connected + */ + public function testUnsubscribesFromSubscribedChannels() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertSame(array('subscribe', 'channel:bar', 2), $redis->subscribe('channel:bar')); + $this->assertSame(array('punsubscribe', 'channel:*', 2), $redis->punsubscribe('channel:*')); + } + + /** + * @group connected + * @todo Disabled for now, must investigate why this test hangs on PUNSUBSCRIBE. + */ + public function __testUnsubscribesFromAllSubscribedChannels() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertSame(array('subscribe', 'channel:bar', 2), $redis->subscribe('channel:bar')); + + $this->assertSame(array('punsubscribe', 'channel:foo', 1), $redis->punsubscribe()); + $this->assertSame(array('punsubscribe', 'channel:bar', 0), $redis->getConnection()->read()); + $this->assertSame('echoed', $redis->echo('echoed')); + } +} diff --git a/tests/Predis/Commands/PubSubUnsubscribeTest.php b/tests/Predis/Commands/PubSubUnsubscribeTest.php new file mode 100644 index 00000000..34f07b5a --- /dev/null +++ b/tests/Predis/Commands/PubSubUnsubscribeTest.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-pubsub + */ +class PubSubUnsubscribeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\PubSubUnsubscribe'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'UNSUBSCRIBE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('channel1', 'channel2', 'channel3'); + $expected = array('channel1', 'channel2', 'channel3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('channel1', 'channel2', 'channel3')); + $expected = array('channel1', 'channel2', 'channel3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('unsubscribe', 'channel', 1); + $expected = array('unsubscribe', 'channel', 1); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array(array('channel1', 'channel2', 'channel3')); + $expected = array('prefix:channel1', 'prefix:channel2', 'prefix:channel3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testDoesNotSwitchToSubscribeMode() + { + $redis = $this->getClient(); + + $this->assertSame(array('unsubscribe', 'channel', 0), $redis->unsubscribe('channel')); + $this->assertSame('echoed', $redis->echo('echoed')); + } + + /** + * @group connected + */ + public function testUnsubscribesFromNotSubscribedChannels() + { + $redis = $this->getClient(); + + $this->assertSame(array('unsubscribe', 'channel', 0), $redis->unsubscribe('channel')); + } + + /** + * @group connected + */ + public function testUnsubscribesFromSubscribedChannels() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel', 1), $redis->subscribe('channel')); + $this->assertSame(array('unsubscribe', 'channel', 0), $redis->unsubscribe('channel')); + } + + /** + * @group connected + */ + public function testUnsubscribesFromAllSubscribedChannels() + { + $redis = $this->getClient(); + + $this->assertSame(array('subscribe', 'channel:foo', 1), $redis->subscribe('channel:foo')); + $this->assertSame(array('subscribe', 'channel:bar', 2), $redis->subscribe('channel:bar')); + + $this->assertSame(array('unsubscribe', 'channel:foo', 1), $redis->unsubscribe()); + $this->assertSame(array('unsubscribe', 'channel:bar', 0), $redis->getConnection()->read()); + $this->assertSame('echoed', $redis->echo('echoed')); + } +} diff --git a/tests/Predis/Commands/ScriptedCommandTest.php b/tests/Predis/Commands/ScriptedCommandTest.php new file mode 100644 index 00000000..48331eaa --- /dev/null +++ b/tests/Predis/Commands/ScriptedCommandTest.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group realm-scripting + */ +class ScriptedCommandTest extends StandardTestCase +{ + const LUA_SCRIPT = 'return { KEYS[1], KEYS[2], ARGV[1], ARGV[2] }'; + + /** + * @group disconnected + */ + public function testGetArguments() + { + $arguments = array('key1', 'key2', 'value1', 'value2'); + + $command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue(self::LUA_SCRIPT)); + $command->expects($this->once()) + ->method('getKeysCount') + ->will($this->returnValue(2)); + $command->setArguments($arguments); + + $this->assertSame(array_merge(array(self::LUA_SCRIPT, 2), $arguments), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testGetKeys() + { + $arguments = array('key1', 'key2', 'value1', 'value2'); + + $command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue(self::LUA_SCRIPT)); + $command->expects($this->exactly(2)) + ->method('getKeysCount') + ->will($this->returnValue(2)); + $command->setArguments($arguments); + + $this->assertSame(array('key1', 'key2'), $command->getKeys()); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('foo', 'hoge', 'bar', 'piyo'); + $expected = array('prefix:foo', 'prefix:hoge'); + + $command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue(self::LUA_SCRIPT)); + $command->expects($this->exactly(2)) + ->method('getKeysCount') + ->will($this->returnValue(2)); + $command->setArguments($arguments); + + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getKeys()); + } + + /** + * @group disconnected + */ + public function testGetScriptHash() + { + $arguments = array('key1', 'key2', 'value1', 'value2'); + + $command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue(self::LUA_SCRIPT)); + $command->expects($this->once()) + ->method('getKeysCount') + ->will($this->returnValue(2)); + $command->setArguments($arguments); + + $this->assertSame(sha1(self::LUA_SCRIPT), $command->getScriptHash()); + } +} diff --git a/tests/Predis/Commands/ServerBackgroundRewriteAOFTest.php b/tests/Predis/Commands/ServerBackgroundRewriteAOFTest.php new file mode 100644 index 00000000..d0c32f2d --- /dev/null +++ b/tests/Predis/Commands/ServerBackgroundRewriteAOFTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerBackgroundRewriteAOFTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerBackgroundRewriteAOF'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'BGREWRITEAOF'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } +} diff --git a/tests/Predis/Commands/ServerBackgroundSaveTest.php b/tests/Predis/Commands/ServerBackgroundSaveTest.php new file mode 100644 index 00000000..5f46da6f --- /dev/null +++ b/tests/Predis/Commands/ServerBackgroundSaveTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerBackgroundSaveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerBackgroundSave'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'BGSAVE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } +} diff --git a/tests/Predis/Commands/ServerClientTest.php b/tests/Predis/Commands/ServerClientTest.php new file mode 100644 index 00000000..0e360dad --- /dev/null +++ b/tests/Predis/Commands/ServerClientTest.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerClientTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerClient'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'CLIENT'; + } + + /** + * @group disconnected + */ + public function testFilterArgumentsOfClientKill() + { + $arguments = array('kill', '127.0.0.1:45393'); + $expected = array('kill', '127.0.0.1:45393'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsOfClientList() + { + $arguments = array('list'); + $expected = array('list'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponseOfClientKill() + { + $command = $this->getCommand(); + $command->setArguments(array('kill')); + + $this->assertSame(true, $command->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testParseResponseOfClientList() + { + $command = $this->getCommand(); + $command->setArguments(array('list')); + + $raw =<<'127.0.0.1:45393','fd'=>'6','idle'=>'0','flags'=>'N','db'=>'0','sub'=>'0','psub'=>'0'), + array('addr'=>'127.0.0.1:45394','fd'=>'7','idle'=>'0','flags'=>'N','db'=>'0','sub'=>'0','psub'=>'0'), + array('addr'=>'127.0.0.1:45395','fd'=>'8','idle'=>'0','flags'=>'N','db'=>'0','sub'=>'0','psub'=>'0'), + ); + + $this->assertSame($parsed, $command->parseResponse($raw)); + } + + /** + * @group connected + */ + public function testReturnsListOfConnectedClients() + { + $redis = $this->getClient(); + + $this->assertInternalType('array', $clients = $redis->client('LIST')); + $this->assertGreaterThanOrEqual(1, count($clients)); + $this->assertInternalType('array', $clients[0]); + $this->assertArrayHasKey('addr', $clients[0]); + $this->assertArrayHasKey('fd', $clients[0]); + $this->assertArrayHasKey('idle', $clients[0]); + $this->assertArrayHasKey('flags', $clients[0]); + $this->assertArrayHasKey('db', $clients[0]); + $this->assertArrayHasKey('sub', $clients[0]); + $this->assertArrayHasKey('psub', $clients[0]); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptioOnWrongModifier() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->client('FOO')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR No such client + */ + public function testThrowsExceptionWhenKillingUnknownClient() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->client('KILL', '127.0.0.1:65535')); + } +} diff --git a/tests/Predis/Commands/ServerConfigTest.php b/tests/Predis/Commands/ServerConfigTest.php new file mode 100644 index 00000000..259d9067 --- /dev/null +++ b/tests/Predis/Commands/ServerConfigTest.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerConfigTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerConfig'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'CONFIG'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('GET', 'slowlog'); + $expected = array('GET', 'slowlog'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponseOfConfigGet() + { + $raw = array('slowlog-log-slower-than','10000','slowlog-max-len','64','loglevel','verbose'); + $expected = array( + 'slowlog-log-slower-than' => '10000', + 'slowlog-max-len' => '64', + 'loglevel' => 'verbose', + ); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testParseResponseOfConfigSet() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testParseResponseOfConfigResetstat() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(true)); + } + + /** + * @group connected + */ + public function testReturnsListOfConfigurationValues() + { + $redis = $this->getClient(); + + $this->assertInternalType('array', $configs = $redis->config('GET', '*')); + $this->assertGreaterThan(1, count($configs)); + $this->assertArrayHasKey('loglevel', $configs); + $this->assertArrayHasKey('appendonly', $configs); + $this->assertArrayHasKey('dbfilename', $configs); + } + + /** + * @group connected + */ + public function testReturnsListOfOneConfigurationEntry() + { + $redis = $this->getClient(); + + $this->assertInternalType('array', $configs = $redis->config('GET', 'dbfilename')); + $this->assertEquals(1, count($configs)); + $this->assertArrayHasKey('dbfilename', $configs); + } + + /** + * @group connected + */ + public function testReturnsEmptyListOnUnknownConfigurationEntry() + { + $redis = $this->getClient(); + + $this->assertSame(array(), $redis->config('GET', 'foobar')); + } + + /** + * @group connected + */ + public function testReturnsTrueOnSuccessfulConfiguration() + { + $redis = $this->getClient(); + + $previous = $redis->config('GET', 'loglevel'); + + $this->assertTrue($redis->config('SET', 'loglevel', 'notice')); + $this->assertSame(array('loglevel' => 'notice'), $redis->config('GET', 'loglevel')); + + // We set the loglevel configuration to the previous value. + $redis->config('SET', 'loglevel', $previous['loglevel']); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Unsupported CONFIG parameter: foo + */ + public function testThrowsExceptionWhenSettingUnknownConfiguration() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->config('SET', 'foo', 'bar')); + } + + /** + * @group connected + */ + public function testReturnsTrueOnResetstat() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->config('RESETSTAT')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnUnknownSubcommand() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->config('FOO')); + } +} diff --git a/tests/Predis/Commands/ServerDatabaseSizeTest.php b/tests/Predis/Commands/ServerDatabaseSizeTest.php new file mode 100644 index 00000000..61b874c3 --- /dev/null +++ b/tests/Predis/Commands/ServerDatabaseSizeTest.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerDatabaseSizeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerDatabaseSize'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'DBSIZE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(100, $this->getCommand()->parseResponse(100)); + } + + /** + * @group connected + */ + public function testReturnsCurrentSizeOfDatabase() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $this->assertGreaterThan(0, $redis->dbsize()); + } +} diff --git a/tests/Predis/Commands/ServerEvalSHATest.php b/tests/Predis/Commands/ServerEvalSHATest.php new file mode 100644 index 00000000..fdc2080d --- /dev/null +++ b/tests/Predis/Commands/ServerEvalSHATest.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-scripting + */ +class ServerEvalSHATest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerEvalSHA'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'EVALSHA'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('9d0c0826bde023cc39eebaaf832c32a890f3b088', 1, 'foo', 'bar'); + $expected = array('9d0c0826bde023cc39eebaaf832c32a890f3b088', 1, 'foo', 'bar'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertSame('bar', $this->getCommand()->parseResponse('bar')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $sha1 = 'a42059b356c875f0717db19a51f6aaca9ae659ea'; + + $arguments = array($sha1, 2, 'foo', 'hoge', 'bar', 'piyo'); + $expected = array($sha1, 2, 'prefix:foo', 'prefix:hoge', 'bar', 'piyo'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testExecutesSpecifiedLuaScript() + { + $redis = $this->getClient(); + + $lua = 'return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}'; + $sha1 = sha1($lua); + $result = array('foo', 'hoge', 'bar', 'piyo'); + + $this->assertSame($result, $redis->eval($lua, 2, 'foo', 'hoge', 'bar', 'piyo')); + $this->assertSame($result, $redis->evalsha($sha1, 2, 'foo', 'hoge', 'bar', 'piyo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnWrongNumberOfKeys() + { + $redis = $this->getClient(); + + $lua = 'return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}'; + $sha1 = sha1($lua); + + $redis->eval($lua, 2, 'foo', 'hoge', 'bar', 'piyo'); + $redis->evalsha($sha1, 3, 'foo', 'hoge'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnInvalidScript() + { + $redis = $this->getClient(); + + $redis->evalsha('ffffffffffffffffffffffffffffffffffffffff', 0); + } +} diff --git a/tests/Predis/Commands/ServerEvalTest.php b/tests/Predis/Commands/ServerEvalTest.php new file mode 100644 index 00000000..0c3ea54a --- /dev/null +++ b/tests/Predis/Commands/ServerEvalTest.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-scripting + */ +class ServerEvalTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerEval'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'EVAL'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('return redis.call("SET", KEYS[1], ARGV[1])', 1, 'foo', 'bar'); + $expected = array('return redis.call("SET", KEYS[1], ARGV[1])', 1, 'foo', 'bar'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertSame('bar', $this->getCommand()->parseResponse('bar')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $lua = 'return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}'; + + $arguments = array($lua, 2, 'foo', 'hoge', 'bar', 'piyo'); + $expected = array($lua, 2, 'prefix:foo', 'prefix:hoge', 'bar', 'piyo'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testGetScriptHash() + { + $command = $this->getCommandWithArgumentsArray(array($lua = 'return true', 0)); + $this->assertSame(sha1($lua), $command->getScriptHash()); + } + + /** + * @group connected + */ + public function testExecutesSpecifiedLuaScript() + { + $redis = $this->getClient(); + + $lua = 'return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}'; + $result = array('foo', 'hoge', 'bar', 'piyo'); + + $this->assertSame($result, $redis->eval($lua, 2, 'foo', 'hoge', 'bar', 'piyo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnWrongNumberOfKeys() + { + $redis = $this->getClient(); + $lua = 'return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}'; + + $redis->eval($lua, 3, 'foo', 'hoge'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnInvalidScript() + { + $redis = $this->getClient(); + + $redis->eval('invalid', 0); + } +} diff --git a/tests/Predis/Commands/ServerFlushAllTest.php b/tests/Predis/Commands/ServerFlushAllTest.php new file mode 100644 index 00000000..6d1303bc --- /dev/null +++ b/tests/Predis/Commands/ServerFlushAllTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerFlushAllTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerFlushAll'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'FLUSHALL'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } +} diff --git a/tests/Predis/Commands/ServerFlushDatabaseTest.php b/tests/Predis/Commands/ServerFlushDatabaseTest.php new file mode 100644 index 00000000..c1af9433 --- /dev/null +++ b/tests/Predis/Commands/ServerFlushDatabaseTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerFlushDatabaseTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerFlushDatabase'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'FLUSHDB'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group connected + */ + public function testFlushesTheEntireLogicalDatabase() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertTrue($redis->flushdb()); + $this->assertFalse($redis->exists('foo')); + } +} diff --git a/tests/Predis/Commands/ServerInfoTest.php b/tests/Predis/Commands/ServerInfoTest.php new file mode 100644 index 00000000..7fc12809 --- /dev/null +++ b/tests/Predis/Commands/ServerInfoTest.php @@ -0,0 +1,289 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerInfoTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerInfo'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'INFO'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw =<< '2.4.4', + 'redis_git_sha1' => 'bc62bc5e', + 'redis_git_dirty' => '0', + 'arch_bits' => '32', + 'multiplexing_api' => 'epoll', + 'process_id' => '15640', + 'uptime_in_seconds' => '792', + 'uptime_in_days' => '0', + 'lru_clock' => '197890', + 'used_cpu_sys' => '0.08', + 'used_cpu_user' => '0.10', + 'used_cpu_sys_children' => '0.00', + 'used_cpu_user_children' => '0.00', + 'connected_clients' => '1', + 'connected_slaves' => '0', + 'client_longest_output_list' => '0', + 'client_biggest_input_buf' => '0', + 'blocked_clients' => '0', + 'used_memory' => '556156', + 'used_memory_human' => '543.12K', + 'used_memory_rss' => '1396736', + 'used_memory_peak' => '547688', + 'used_memory_peak_human' => '534.85K', + 'mem_fragmentation_ratio' => '2.51', + 'mem_allocator' => 'jemalloc-2.2.1', + 'loading' => '0', + 'aof_enabled' => '0', + 'changes_since_last_save' => '0', + 'bgsave_in_progress' => '0', + 'last_save_time' => '1323183872', + 'bgrewriteaof_in_progress' => '0', + 'total_connections_received' => '2', + 'total_commands_processed' => '1', + 'expired_keys' => '0', + 'evicted_keys' => '0', + 'keyspace_hits' => '0', + 'keyspace_misses' => '0', + 'pubsub_channels' => '0', + 'pubsub_patterns' => '0', + 'latest_fork_usec' => '0', + 'vm_enabled' => '0', + 'role' => 'master', + 'db0' => array('keys' => '2', 'expires' => '0'), + 'db5' => array('keys' => '1', 'expires' => '0'), + ); + + $this->assertSame($expected, $this->getCommand()->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testCanParseResponsesFromRedis30() + { + $raw =<< '2.9.0', + 'redis_git_sha1' => '237194b7', + 'redis_git_dirty' => '0', + 'arch_bits' => '32', + 'multiplexing_api' => 'epoll', + 'process_id' => '16620', + 'tcp_port' => '6379', + 'uptime_in_seconds' => '444', + 'uptime_in_days' => '0', + 'lru_clock' => '198040', + 'connected_clients' => '1', + 'client_longest_output_list' => '0', + 'client_biggest_input_buf' => '0', + 'blocked_clients' => '0', + 'used_memory' => '628076', + 'used_memory_human' => '613.36K', + 'used_memory_rss' => '1568768', + 'used_memory_peak' => '570056', + 'used_memory_peak_human' => '556.70K', + 'used_memory_lua' => '14336', + 'mem_fragmentation_ratio' => '2.50', + 'mem_allocator' => 'jemalloc-2.2.1', + 'loading' => '0', + 'aof_enabled' => '0', + 'changes_since_last_save' => '0', + 'bgsave_in_progress' => '0', + 'last_save_time' => '1323185719', + 'bgrewriteaof_in_progress' => '0', + 'total_connections_received' => '4', + 'total_commands_processed' => '3', + 'rejected_connections' => '0', + 'expired_keys' => '0', + 'evicted_keys' => '0', + 'keyspace_hits' => '0', + 'keyspace_misses' => '0', + 'pubsub_channels' => '0', + 'pubsub_patterns' => '0', + 'latest_fork_usec' => '0', + 'role' => 'master', + 'connected_slaves' => '0', + 'used_cpu_sys' => '0.06', + 'used_cpu_user' => '0.06', + 'used_cpu_sys_children' => '0.00', + 'used_cpu_user_children' => '0.00', + 'cluster_enabled' => '0', + 'db0' => array('keys' => '2', 'expires' => '0'), + 'db5' => array('keys' => '1','expires' => '0'), + ); + + $this->assertSame($expected, $this->getCommand()->parseResponse($raw)); + } + + /** + * @group connected + */ + public function testReturnsAnArrayOfInfo() + { + $redis = $this->getClient(); + $command = $this->getCommand(); + + $this->assertInternalType('array', $info = $redis->executeCommand($command)); + $this->assertArrayHasKey('redis_version', $info); + } +} diff --git a/tests/Predis/Commands/ServerInfoV26xTest.php b/tests/Predis/Commands/ServerInfoV26xTest.php new file mode 100644 index 00000000..6fd79f4a --- /dev/null +++ b/tests/Predis/Commands/ServerInfoV26xTest.php @@ -0,0 +1,307 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerInfoV26xTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerInfoV26x'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'INFO'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw =<< array( + 'redis_version' => '2.9.0', + 'redis_git_sha1' => '237194b7', + 'redis_git_dirty' => '0', + 'arch_bits' => '32', + 'multiplexing_api' => 'epoll', + 'process_id' => '16620', + 'tcp_port' => '6379', + 'uptime_in_seconds' => '444', + 'uptime_in_days' => '0', + 'lru_clock' => '198040', + ), + 'Clients' => array( + 'connected_clients' => '1', + 'client_longest_output_list' => '0', + 'client_biggest_input_buf' => '0', + 'blocked_clients' => '0', + ), + 'Memory' => array( + 'used_memory' => '628076', + 'used_memory_human' => '613.36K', + 'used_memory_rss' => '1568768', + 'used_memory_peak' => '570056', + 'used_memory_peak_human' => '556.70K', + 'used_memory_lua' => '14336', + 'mem_fragmentation_ratio' => '2.50', + 'mem_allocator' => 'jemalloc-2.2.1', + ), + 'Persistence' => array( + 'loading' => '0', + 'aof_enabled' => '0', + 'changes_since_last_save' => '0', + 'bgsave_in_progress' => '0', + 'last_save_time' => '1323185719', + 'bgrewriteaof_in_progress' => '0', + ), + 'Stats' => array( + 'total_connections_received' => '4', + 'total_commands_processed' => '3', + 'rejected_connections' => '0', + 'expired_keys' => '0', + 'evicted_keys' => '0', + 'keyspace_hits' => '0', + 'keyspace_misses' => '0', + 'pubsub_channels' => '0', + 'pubsub_patterns' => '0', + 'latest_fork_usec' => '0', + ), + 'Replication' => array( + 'role' => 'master', + 'connected_slaves' => '0', + ), + 'CPU' => array( + 'used_cpu_sys' => '0.06', + 'used_cpu_user' => '0.06', + 'used_cpu_sys_children' => '0.00', + 'used_cpu_user_children' => '0.00', + ), + 'Cluster' => array( + 'cluster_enabled' => '0', + ), + 'Keyspace' => array( + 'db0' => array('keys' => '2', 'expires' => '0'), + 'db5' => array('keys' => '1', 'expires' => '0') + ), + ); + + $this->assertSame($expected, $this->getCommand()->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testCanParseResponsesFromOlderRedisVersions() + { + $raw =<< '2.4.4', + 'redis_git_sha1' => 'bc62bc5e', + 'redis_git_dirty' => '0', + 'arch_bits' => '32', + 'multiplexing_api' => 'epoll', + 'process_id' => '15640', + 'uptime_in_seconds' => '792', + 'uptime_in_days' => '0', + 'lru_clock' => '197890', + 'used_cpu_sys' => '0.08', + 'used_cpu_user' => '0.10', + 'used_cpu_sys_children' => '0.00', + 'used_cpu_user_children' => '0.00', + 'connected_clients' => '1', + 'connected_slaves' => '0', + 'client_longest_output_list' => '0', + 'client_biggest_input_buf' => '0', + 'blocked_clients' => '0', + 'used_memory' => '556156', + 'used_memory_human' => '543.12K', + 'used_memory_rss' => '1396736', + 'used_memory_peak' => '547688', + 'used_memory_peak_human' => '534.85K', + 'mem_fragmentation_ratio' => '2.51', + 'mem_allocator' => 'jemalloc-2.2.1', + 'loading' => '0', + 'aof_enabled' => '0', + 'changes_since_last_save' => '0', + 'bgsave_in_progress' => '0', + 'last_save_time' => '1323183872', + 'bgrewriteaof_in_progress' => '0', + 'total_connections_received' => '2', + 'total_commands_processed' => '1', + 'expired_keys' => '0', + 'evicted_keys' => '0', + 'keyspace_hits' => '0', + 'keyspace_misses' => '0', + 'pubsub_channels' => '0', + 'pubsub_patterns' => '0', + 'latest_fork_usec' => '0', + 'vm_enabled' => '0', + 'role' => 'master', + 'db0' => array('keys' => '2', 'expires' => '0'), + 'db5' => array('keys' => '1', 'expires' => '0'), + ); + + $this->assertSame($expected, $this->getCommand()->parseResponse($raw)); + } + + /** + * @group connected + */ + public function testReturnsAnArrayOfInfo() + { + $redis = $this->getClient(); + $command = $this->getCommand(); + + $this->assertInternalType('array', $info = $redis->executeCommand($command)); + $this->assertArrayHasKey('redis_version', isset($info['Server']) ? $info['Server'] : $info); + } +} diff --git a/tests/Predis/Commands/ServerLastSaveTest.php b/tests/Predis/Commands/ServerLastSaveTest.php new file mode 100644 index 00000000..e74581b2 --- /dev/null +++ b/tests/Predis/Commands/ServerLastSaveTest.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerLastSaveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerLastSave'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'LASTSAVE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(100, $this->getCommand()->parseResponse(100)); + } + + /** + * @group connected + */ + public function testReturnsIntegerValue() + { + $redis = $this->getClient(); + + $this->assertInternalType('integer', $redis->lastsave()); + } +} diff --git a/tests/Predis/Commands/ServerMonitorTest.php b/tests/Predis/Commands/ServerMonitorTest.php new file mode 100644 index 00000000..b1df9714 --- /dev/null +++ b/tests/Predis/Commands/ServerMonitorTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + * @group realm-monitor + */ +class ServerMonitorTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerMonitor'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'MONITOR'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group connected + */ + public function testReturnsTrueAndReadsEventsFromTheConnection() + { + $connection = $this->getClient()->getConnection(); + $command = $this->getCommand(); + + $this->assertTrue($connection->executeCommand($command)); + $this->assertRegExp('/\d+.\d+(\s?\(db \d+\))? "MONITOR"/', $connection->read()); + } +} diff --git a/tests/Predis/Commands/ServerObjectTest.php b/tests/Predis/Commands/ServerObjectTest.php new file mode 100644 index 00000000..03b8c6ac --- /dev/null +++ b/tests/Predis/Commands/ServerObjectTest.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerObjectTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerObject'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'OBJECT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('REFCOUNT', 'key'); + $expected = array('REFCOUNT', 'key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('ziplist', $this->getCommand()->parseResponse('ziplist')); + } + + /** + * @group connected + */ + public function testObjectRefcount() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $this->assertInternalType('integer', $redis->object('REFCOUNT', 'foo')); + } + + /** + * @group connected + */ + public function testObjectIdletime() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $this->assertInternalType('integer', $redis->object('IDLETIME', 'foo')); + } + + /** + * @group connected + */ + public function testObjectEncoding() + { + $redis = $this->getClient(); + + $redis->lpush('list:metavars', 'foo', 'bar'); + $this->assertSame('ziplist', $redis->object('ENCODING', 'list:metavars')); + } + + /** + * @group connected + */ + public function testReturnsNullOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertNull($redis->object('REFCOUNT', 'foo')); + $this->assertNull($redis->object('IDLETIME', 'foo')); + $this->assertNull($redis->object('ENCODING', 'foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnInvalidSubcommand() + { + $redis = $this->getClient(); + + $redis->object('INVALID', 'foo'); + } +} diff --git a/tests/Predis/Commands/ServerSaveTest.php b/tests/Predis/Commands/ServerSaveTest.php new file mode 100644 index 00000000..7101699d --- /dev/null +++ b/tests/Predis/Commands/ServerSaveTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerSaveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerSave'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SAVE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } +} diff --git a/tests/Predis/Commands/ServerScriptTest.php b/tests/Predis/Commands/ServerScriptTest.php new file mode 100644 index 00000000..cb9e3847 --- /dev/null +++ b/tests/Predis/Commands/ServerScriptTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-scripting + */ +class ServerScriptTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerScript'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SCRIPT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('EXISTS', '9d0c0826bde023cc39eebaaf832c32a890f3b088', 'ffffffffffffffffffffffffffffffffffffffff'); + $expected = array('EXISTS', '9d0c0826bde023cc39eebaaf832c32a890f3b088', 'ffffffffffffffffffffffffffffffffffffffff'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group connected + * @todo We should probably convert integers to booleans. + */ + public function testExistsReturnAnArrayOfValues() + { + $redis = $this->getClient(); + + $redis->eval($lua = 'return true', 0); + $sha1 = sha1($lua); + + $this->assertSame(array(1, 0), $redis->script('EXISTS', $sha1, 'ffffffffffffffffffffffffffffffffffffffff')); + } + + /** + * @group connected + */ + public function testLoadReturnsHashOfScripts() + { + $redis = $this->getClient(); + + $lua = 'return true'; + $sha1 = sha1($lua); + + $this->assertSame($sha1, $redis->script('LOAD', $lua)); + } + + /** + * @group connected + */ + public function testFlushesExistingScripts() + { + $redis = $this->getClient(); + + $sha1 = $redis->script('LOAD', 'return true'); + + $this->assertTrue($redis->script('FLUSH')); + $this->assertSame(array(0), $redis->script('EXISTS', $sha1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnInvalidSubcommand() + { + $redis = $this->getClient(); + + $redis->script('INVALID'); + } +} diff --git a/tests/Predis/Commands/ServerShutdownTest.php b/tests/Predis/Commands/ServerShutdownTest.php new file mode 100644 index 00000000..5402c761 --- /dev/null +++ b/tests/Predis/Commands/ServerShutdownTest.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerShutdownTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerShutdown'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SHUTDOWN'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } +} diff --git a/tests/Predis/Commands/ServerSlaveOfTest.php b/tests/Predis/Commands/ServerSlaveOfTest.php new file mode 100644 index 00000000..ad77dbe0 --- /dev/null +++ b/tests/Predis/Commands/ServerSlaveOfTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-server + */ +class ServerSlaveOfTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerSlaveOf'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SLAVEOF'; + } + + /** + * @group disconnected + */ + public function testFilterArgumentsHostPortArray() + { + $arguments = array('127.0.0.1', '80'); + $expected = array('127.0.0.1', '80'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsNoOneArray() + { + $arguments = array('NO', 'ONE'); + $expected = array('NO', 'ONE'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsNoOneString() + { + $arguments = array('NO ONE'); + $expected = array('NO', 'ONE'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } +} diff --git a/tests/Predis/Commands/ServerSlowlogTest.php b/tests/Predis/Commands/ServerSlowlogTest.php new file mode 100644 index 00000000..92f579cc --- /dev/null +++ b/tests/Predis/Commands/ServerSlowlogTest.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * In order to support the output of SLOWLOG, the backend connection + * must be able to parse nested multibulk replies deeper than 2 levels. + * + * @group commands + * @group realm-server + */ +class ServerSlowlogTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ServerSlowlog'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SLOWLOG'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('GET', '2'); + $expected = array('GET', '2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array(array(0, 1323163469, 12451, array('SORT', 'list:unordered'))); + $expected = array( + array( + 'id' => 0, + 'timestamp' => 1323163469, + 'duration' => 12451, + 'command' => array('SORT', 'list:unordered'), + ), + ); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group connected + */ + public function testReturnsAnArrayOfLoggedCommands() + { + $redis = $this->getClient(); + + $threshold = array_pop($redis->config('get', 'slowlog-log-slower-than')); + + $redis->config('set', 'slowlog-log-slower-than', 0); + $redis->set('foo', 'bar'); + + $this->assertInternalType('array', $slowlog = $redis->slowlog('GET')); + $this->assertGreaterThan(0, count($slowlog)); + + $this->assertInternalType('array', $slowlog[0]); + $this->assertGreaterThan(0, $slowlog[0]['id']); + $this->assertGreaterThan(0, $slowlog[0]['timestamp']); + $this->assertGreaterThan(0, $slowlog[0]['duration']); + $this->assertInternalType('array', $slowlog[0]['command']); + + $redis->config('set', 'slowlog-log-slower-than', $threshold); + } + + /** + * @group connected + */ + public function testCanResetTheLog() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->slowlog('RESET')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + */ + public function testThrowsExceptionOnInvalidSubcommand() + { + $redis = $this->getClient(); + + $redis->slowlog('INVALID'); + } +} diff --git a/tests/Predis/Commands/SetAddTest.php b/tests/Predis/Commands/SetAddTest.php new file mode 100644 index 00000000..a15c4bc9 --- /dev/null +++ b/tests/Predis/Commands/SetAddTest.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetAddTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetAdd'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SADD'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'member1', 'member2', 'member3'); + $expected = array('key', 'member1', 'member2', 'member3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsValuesAsSingleArray() + { + $arguments = array('key', array('member1', 'member2', 'member3')); + $expected = array('key', 'member1', 'member2', 'member3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'member1', 'member2', 'member3'); + $expected = array('prefix:key', 'member1', 'member2', 'member3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testAddsMembersToSet() + { + $redis = $this->getClient(); + + $this->assertSame(1, $redis->sadd('letters', 'a')); + $this->assertSame(2, $redis->sadd('letters', 'b', 'c')); + $this->assertSame(0, $redis->sadd('letters', 'b')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->sadd('metavars', 'hoge'); + } +} diff --git a/tests/Predis/Commands/SetCardinalityTest.php b/tests/Predis/Commands/SetCardinalityTest.php new file mode 100644 index 00000000..49ce7502 --- /dev/null +++ b/tests/Predis/Commands/SetCardinalityTest.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetCardinalityTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetCardinality'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SCARD'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsNumberOfMembers() + { + $redis = $this->getClient(); + + $redis->sadd('letters', 'a', 'b', 'c', 'd'); + + $this->assertSame(4, $redis->scard('letters')); + } + + /** + * @group connected + */ + public function testReturnsZeroOnEmptySet() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->scard('letters')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('metavars', 'foo'); + $redis->scard('metavars'); + } +} diff --git a/tests/Predis/Commands/SetDifferenceStoreTest.php b/tests/Predis/Commands/SetDifferenceStoreTest.php new file mode 100644 index 00000000..010f1593 --- /dev/null +++ b/tests/Predis/Commands/SetDifferenceStoreTest.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetDifferenceStoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetDifferenceStore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SDIFFSTORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key:destination', 'key:source1', 'key:source:2'); + $expected = array('key:destination', 'key:source1', 'key:source:2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsSourceKeysAsSingleArray() + { + $arguments = array('key:destination', array('key:source1', 'key:source:2')); + $expected = array('key:destination', 'key:source1', 'key:source:2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key:destination', 'key:source1', 'key:source:2'); + $expected = array('prefix:key:destination', 'prefix:key:source1', 'prefix:key:source:2'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testStoresMembersOfSetOnSingleSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSame(7, $redis->sdiffstore('letters:destination', 'letters:1st')); + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->smembers('letters:destination')); + } + + /** + * @group connected + */ + public function testStoresDifferenceOfMultipleSets() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + $redis->sadd('letters:2nd', 'a', 'c', 'f', 'g'); + $redis->sadd('letters:3rd', 'a', 'b', 'e', 'f'); + + $this->assertSame(3, $redis->sdiffstore('letters:destination', 'letters:1st', 'letters:2nd')); + $this->assertSameValues(array('b', 'd', 'e'), $redis->smembers('letters:destination')); + + $this->assertSame(1, $redis->sdiffstore('letters:destination', 'letters:1st', 'letters:2nd', 'letters:3rd')); + $this->assertSameValues(array('d'), $redis->smembers('letters:destination')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongTypeOfSourceKey() + { + $redis = $this->getClient(); + + $redis->set('set:source', 'foo'); + $redis->sdiffstore('set:destination', 'set:source'); + } +} diff --git a/tests/Predis/Commands/SetDifferenceTest.php b/tests/Predis/Commands/SetDifferenceTest.php new file mode 100644 index 00000000..6da34cfe --- /dev/null +++ b/tests/Predis/Commands/SetDifferenceTest.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetDifferenceTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetDifference'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SDIFF'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3')); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('member1', 'member2', 'member3'); + $expected = array('member1', 'member2', 'member3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsMembersOnSingleKeyOrNonExistingSetForDifference() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->sdiff('letters:1st')); + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->sdiff('letters:1st', 'letters:2nd')); + } + + /** + * @group connected + */ + public function testReturnsMembersFromDifferenceAmongSets() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + $redis->sadd('letters:2nd', 'a', 'c', 'f', 'g'); + $redis->sadd('letters:3rd', 'a', 'b', 'e', 'f'); + + $this->assertSameValues(array('b', 'd', 'e'), $redis->sdiff('letters:1st', 'letters:2nd')); + $this->assertSameValues(array('d'), $redis->sdiff('letters:1st', 'letters:2nd', 'letters:3rd')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('set:foo', 'a'); + $redis->sdiff('set:foo'); + } +} diff --git a/tests/Predis/Commands/SetIntersectionStoreTest.php b/tests/Predis/Commands/SetIntersectionStoreTest.php new file mode 100644 index 00000000..06c3a875 --- /dev/null +++ b/tests/Predis/Commands/SetIntersectionStoreTest.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetIntersectionStoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetIntersectionStore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SINTERSTORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key:destination', 'key:source1', 'key:source:2'); + $expected = array('key:destination', 'key:source1', 'key:source:2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsSourceKeysAsSingleArray() + { + $arguments = array('key:destination', array('key:source1', 'key:source:2')); + $expected = array('key:destination', 'key:source1', 'key:source:2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key:destination', 'key:source1', 'key:source:2'); + $expected = array('prefix:key:destination', 'prefix:key:source1', 'prefix:key:source:2'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testStoresMembersOfSetOnSingleKey() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSame(7, $redis->sinterstore('letters:destination', 'letters:1st')); + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->smembers('letters:destination')); + } + + /** + * @group connected + */ + public function testDoesNotStoreOnNonExistingSetForIntersection() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSame(0, $redis->sinterstore('letters:destination', 'letters:1st', 'letters:2nd')); + $this->assertFalse($redis->exists('letters:destination')); + } + + /** + * @group connected + */ + public function testStoresIntersectionOfMultipleSets() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + $redis->sadd('letters:2nd', 'a', 'c', 'f', 'g'); + $redis->sadd('letters:3rd', 'a', 'b', 'e', 'f'); + + $this->assertSame(4, $redis->sinterstore('letters:destination', 'letters:1st', 'letters:2nd')); + $this->assertSameValues(array('a', 'c', 'f', 'g'), $redis->smembers('letters:destination')); + + $this->assertSame(2, $redis->sinterstore('letters:destination', 'letters:1st', 'letters:2nd', 'letters:3rd')); + $this->assertSameValues(array('a', 'f'), $redis->smembers('letters:destination')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongTypeOfSourceKey() + { + $redis = $this->getClient(); + + $redis->set('set:source', 'foo'); + $redis->sinterstore('set:destination', 'set:source'); + } +} diff --git a/tests/Predis/Commands/SetIntersectionTest.php b/tests/Predis/Commands/SetIntersectionTest.php new file mode 100644 index 00000000..bd9edcc1 --- /dev/null +++ b/tests/Predis/Commands/SetIntersectionTest.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetIntersectionTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetIntersection'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SINTER'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3')); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('member1', 'member2', 'member3'); + $expected = array('member1', 'member2', 'member3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsMembersOfSetOnSingleKey() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSameValues(array('a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->sinter('letters:1st')); + } + + /** + * @group connected + */ + public function testReturnsEmptyArrayOnNonExistingSetForIntersection() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSameValues(array(), $redis->sinter('letters:1st', 'letters:2nd')); + } + + /** + * @group connected + */ + public function testReturnsMembersFromIntersectionAmongSets() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + $redis->sadd('letters:2nd', 'a', 'c', 'f', 'g'); + $redis->sadd('letters:3rd', 'a', 'b', 'e', 'f'); + + $this->assertSameValues(array('a', 'c', 'f', 'g'), $redis->sinter('letters:1st', 'letters:2nd')); + $this->assertSameValues(array('a', 'f'), $redis->sinter('letters:1st', 'letters:2nd', 'letters:3rd')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('set:foo', 'a'); + $redis->sinter('set:foo'); + } +} diff --git a/tests/Predis/Commands/SetIsMemberTest.php b/tests/Predis/Commands/SetIsMemberTest.php new file mode 100644 index 00000000..b07a5d9e --- /dev/null +++ b/tests/Predis/Commands/SetIsMemberTest.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetIsMemberTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetIsMember'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SISMEMBER'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'member'); + $expected = array('key', 'member'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'member'); + $expected = array('prefix:key', 'member'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsMemberExistenceInSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters', 'a', 'b', 'c'); + + $this->assertTrue($redis->sismember('letters', 'a')); + $this->assertFalse($redis->sismember('letters', 'z')); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExistingSet() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->sismember('letters', 'a')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->sismember('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/SetMembersTest.php b/tests/Predis/Commands/SetMembersTest.php new file mode 100644 index 00000000..618155e2 --- /dev/null +++ b/tests/Predis/Commands/SetMembersTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetMembersTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetMembers'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SMEMBERS'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('member1', 'member2', 'member3'); + $expected = array('member1', 'member2', 'member3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsFalseOnNonExistingSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters', 'a', 'b', 'c', 'd', 'e'); + + $this->assertSameValues(array('a', 'b', 'c', 'd', 'e'), $redis->smembers('letters')); + $this->assertSame(array(), $redis->smembers('digits')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->smembers('foo'); + } +} diff --git a/tests/Predis/Commands/SetMoveTest.php b/tests/Predis/Commands/SetMoveTest.php new file mode 100644 index 00000000..5114905b --- /dev/null +++ b/tests/Predis/Commands/SetMoveTest.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetMoveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetMove'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SMOVE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key:source', 'key:destination', 'member'); + $expected = array('key:source', 'key:destination', 'member'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + + $this->assertTrue($command->parseResponse(1)); + $this->assertFalse($command->parseResponse(0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key:source', 'key:destination', 'member'); + $expected = array('prefix:key:source', 'prefix:key:destination', 'member'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsMemberExistenceInSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters:source', 'a', 'b', 'c'); + + $this->assertTrue($redis->smove('letters:source', 'letters:destination', 'b')); + $this->assertFalse($redis->smove('letters:source', 'letters:destination', 'z')); + + $this->assertSameValues(array('a', 'c'), $redis->smembers('letters:source')); + $this->assertSameValues(array('b'), $redis->smembers('letters:destination')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongTypeOfSourceKey() + { + $redis = $this->getClient(); + + $redis->set('set:source', 'foo'); + $redis->sadd('set:destination', 'bar'); + $redis->smove('set:destination', 'set:source', 'foo'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongTypeOfDestinationKey() + { + $redis = $this->getClient(); + + $redis->sadd('set:source', 'foo'); + $redis->set('set:destination', 'bar'); + $redis->smove('set:destination', 'set:source', 'foo'); + } +} diff --git a/tests/Predis/Commands/SetPopTest.php b/tests/Predis/Commands/SetPopTest.php new file mode 100644 index 00000000..b39426f1 --- /dev/null +++ b/tests/Predis/Commands/SetPopTest.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetPopTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetPop'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SPOP'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('member', $this->getCommand()->parseResponse('member')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testPopsRandomMemberFromSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters', 'a', 'b'); + + $this->assertContains($redis->spop('letters'), array('a', 'b')); + $this->assertContains($redis->spop('letters'), array('a', 'b')); + + $this->assertNull($redis->spop('letters')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->spop('foo'); + } +} diff --git a/tests/Predis/Commands/SetRandomMemberTest.php b/tests/Predis/Commands/SetRandomMemberTest.php new file mode 100644 index 00000000..a9e3320c --- /dev/null +++ b/tests/Predis/Commands/SetRandomMemberTest.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetRandomMemberTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetRandomMember'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SRANDMEMBER'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('member', $this->getCommand()->parseResponse('member')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsRandomMemberFromSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters', 'a', 'b'); + + $this->assertContains($redis->srandmember('letters'), array('a', 'b')); + $this->assertContains($redis->srandmember('letters'), array('a', 'b')); + + $this->assertSame(2, $redis->scard('letters')); + } + + /** + * @group connected + */ + public function testReturnsNullOnNonExistingSet() + { + $this->assertNull($this->getClient()->srandmember('letters')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->srandmember('foo'); + } +} diff --git a/tests/Predis/Commands/SetRemoveTest.php b/tests/Predis/Commands/SetRemoveTest.php new file mode 100644 index 00000000..b8d5e55b --- /dev/null +++ b/tests/Predis/Commands/SetRemoveTest.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetRemoveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetRemove'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SREM'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'member1', 'member2', 'member3'); + $expected = array('key', 'member1', 'member2', 'member3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsMembersAsSingleArray() + { + $arguments = array('key', array('member1', 'member2', 'member3')); + $expected = array('key', 'member1', 'member2', 'member3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'member1', 'member2', 'member3'); + $expected = array('prefix:key', 'member1', 'member2', 'member3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRemovesMembersFromSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters', 'a', 'b', 'c', 'd'); + + $this->assertSame(1, $redis->srem('letters', 'b')); + $this->assertSame(1, $redis->srem('letters', 'd', 'z')); + $this->assertSameValues(array('a', 'c'), $redis->smembers('letters')); + + $this->assertSame(0, $redis->srem('digits', 1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->srem('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/SetUnionStoreTest.php b/tests/Predis/Commands/SetUnionStoreTest.php new file mode 100644 index 00000000..e83cb982 --- /dev/null +++ b/tests/Predis/Commands/SetUnionStoreTest.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetUnionStoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetUnionStore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SUNIONSTORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key:destination', 'key:source1', 'key:source:2'); + $expected = array('key:destination', 'key:source1', 'key:source:2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsSourceKeysAsSingleArray() + { + $arguments = array('key:destination', array('key:source1', 'key:source:2')); + $expected = array('key:destination', 'key:source1', 'key:source:2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key:destination', 'key:source1', 'key:source:2'); + $expected = array('prefix:key:destination', 'prefix:key:source1', 'prefix:key:source:2'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testStoresMembersOfSetOnSingleSet() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSame(7, $redis->sunionstore('letters:destination', 'letters:1st')); + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->smembers('letters:destination')); + } + + /** + * @group connected + */ + public function testStoresUnionOfMultipleSets() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'b', 'd', 'f'); + $redis->sadd('letters:2nd', 'a', 'c', 'g'); + $redis->sadd('letters:3rd', 'a', 'e', 'f'); + + $this->assertSame(5, $redis->sunionstore('letters:destination', 'letters:2nd', 'letters:3rd')); + $this->assertSameValues(array('a', 'c', 'e', 'f', 'g'), $redis->smembers('letters:destination')); + + $this->assertSame(7, $redis->sunionstore('letters:destination', 'letters:1st', 'letters:2nd', 'letters:3rd')); + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->smembers('letters:destination')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongTypeOfSourceKey() + { + $redis = $this->getClient(); + + $redis->set('set:source', 'foo'); + $redis->sunionstore('set:destination', 'set:source'); + } +} diff --git a/tests/Predis/Commands/SetUnionTest.php b/tests/Predis/Commands/SetUnionTest.php new file mode 100644 index 00000000..cf638597 --- /dev/null +++ b/tests/Predis/Commands/SetUnionTest.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-set + */ +class SetUnionTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\SetUnion'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SUNION'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3')); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('member1', 'member2', 'member3'); + $expected = array('member1', 'member2', 'member3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsMembersOnSingleKeyOrNonExistingSetForUnion() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'a', 'b', 'c', 'd', 'e', 'f', 'g'); + + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->sunion('letters:1st')); + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->sunion('letters:1st', 'letters:2nd')); + } + + /** + * @group connected + */ + public function testReturnsMembersFromDifferenceAmongSets() + { + $redis = $this->getClient(); + + $redis->sadd('letters:1st', 'b', 'd', 'f'); + $redis->sadd('letters:2nd', 'a', 'c', 'g'); + $redis->sadd('letters:3rd', 'a', 'e', 'f'); + + $this->assertSameValues(array('a', 'c', 'e', 'f', 'g'), $redis->sunion('letters:2nd', 'letters:3rd')); + $this->assertSameValues(array( 'a', 'b', 'c', 'd', 'e', 'f', 'g'), $redis->sunion('letters:1st', 'letters:2nd', 'letters:3rd')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('set:foo', 'a'); + $redis->sunion('set:foo'); + } +} diff --git a/tests/Predis/Commands/StringAppendTest.php b/tests/Predis/Commands/StringAppendTest.php new file mode 100644 index 00000000..ae4e2069 --- /dev/null +++ b/tests/Predis/Commands/StringAppendTest.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringAppendTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringAppend'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'APPEND'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'value'); + $expected = array('key', 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(10, $this->getCommand()->parseResponse(10)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(3, $redis->append('foo', 'bar')); + $this->assertSame('bar', $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsTheLenghtOfTheStringAfterAppend() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertSame(5, $redis->append('foo', '__')); + $this->assertSame(8, $redis->append('foo', 'bar')); + $this->assertSame('bar__bar', $redis->get('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->append('metavars', 'bar'); + } +} diff --git a/tests/Predis/Commands/StringDecrementByTest.php b/tests/Predis/Commands/StringDecrementByTest.php new file mode 100644 index 00000000..8cdbbd49 --- /dev/null +++ b/tests/Predis/Commands/StringDecrementByTest.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringDecrementByTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringDecrementBy'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'DECRBY'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 5); + $expected = array('key', 5); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(5, $this->getCommand()->parseResponse(5)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 5); + $expected = array('prefix:key', 5); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(-10, $redis->decrby('foo', 10)); + $this->assertEquals(-10, $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsTheValueOfTheKeyAfterDecrement() + { + $redis = $this->getClient(); + + $redis->set('foo', 10); + + $this->assertSame(6, $redis->decrby('foo', 4)); + $this->assertSame(0, $redis->decrby('foo', 6)); + $this->assertSame(-25, $redis->decrby('foo', 25)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not an integer or out of range + */ + public function testThrowsExceptionOnDecrementValueNotInteger() + { + $redis = $this->getClient(); + + $redis->decrby('foo', 'bar'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not an integer or out of range + */ + public function testThrowsExceptionOnKeyValueNotInteger() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->decrby('foo', 5); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->decrby('metavars', 10); + } +} diff --git a/tests/Predis/Commands/StringDecrementTest.php b/tests/Predis/Commands/StringDecrementTest.php new file mode 100644 index 00000000..9dfbc213 --- /dev/null +++ b/tests/Predis/Commands/StringDecrementTest.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringDecrementTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringDecrement'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'DECR'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(5, $this->getCommand()->parseResponse(5)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(-1, $redis->decr('foo')); + $this->assertEquals(-1, $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsTheValueOfTheKeyAfterDecrement() + { + $redis = $this->getClient(); + + $redis->set('foo', 1); + + $this->assertSame(0, $redis->decr('foo')); + $this->assertSame(-1, $redis->decr('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not an integer or out of range + */ + public function testThrowsExceptionOnKeyValueNotInteger() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->decr('foo'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->decr('metavars'); + } +} diff --git a/tests/Predis/Commands/StringGetBitTest.php b/tests/Predis/Commands/StringGetBitTest.php new file mode 100644 index 00000000..8acfac2f --- /dev/null +++ b/tests/Predis/Commands/StringGetBitTest.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringGetBitTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringGetBit'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'GETBIT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 100); + $expected = array('key', 100); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + $this->assertSame(0, $command->parseResponse(0)); + $this->assertSame(1, $command->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 100); + $expected = array('prefix:key', 100); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCanGetBitsFromString() + { + $redis = $this->getClient(); + + $redis->set('key:binary', "\x80\x00\00\x01"); + + $this->assertSame(1, $redis->getbit('key:binary', 0)); + $this->assertSame(0, $redis->getbit('key:binary', 15)); + $this->assertSame(1, $redis->getbit('key:binary', 31)); + $this->assertSame(0, $redis->getbit('key:binary', 63)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR bit offset is not an integer or out of range + */ + public function testThrowsExceptionOnNegativeOffset() + { + $redis = $this->getClient(); + + $redis->set('key:binary', "\x80\x00\00\x01"); + $redis->getbit('key:binary', -1); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR bit offset is not an integer or out of range + */ + public function testThrowsExceptionOnInvalidOffset() + { + $redis = $this->getClient(); + + $redis->set('key:binary', "\x80\x00\00\x01"); + $redis->getbit('key:binary', 'invalid'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->getbit('metavars', '1'); + } +} diff --git a/tests/Predis/Commands/StringGetMultipleTest.php b/tests/Predis/Commands/StringGetMultipleTest.php new file mode 100644 index 00000000..2a6f47df --- /dev/null +++ b/tests/Predis/Commands/StringGetMultipleTest.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringGetMultipleTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringGetMultiple'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'MGET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3')); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('value1', 'value2', 'value3'); + $expected = array('value1', 'value2', 'value3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + + /** + * @group connected + */ + public function testReturnsArrayOfValues() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->set('hoge', 'piyo'); + + $this->assertSame(array('bar', 'piyo'), $redis->mget('foo', 'hoge')); + } + + /** + * @group connected + */ + public function testReturnsArrayWithNullValuesOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertSame(array(null, null), $redis->mget('foo', 'hoge')); + } + + /** + * @group connected + */ + public function testDoesNotThrowExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $this->assertSame(array(null), $redis->mget('metavars')); + } +} diff --git a/tests/Predis/Commands/StringGetRangeTest.php b/tests/Predis/Commands/StringGetRangeTest.php new file mode 100644 index 00000000..425a7e6e --- /dev/null +++ b/tests/Predis/Commands/StringGetRangeTest.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringGetRangeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringGetRange'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'GETRANGE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 5, 10); + $expected = array('key', 5, 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('substring',$this->getCommand()->parseResponse('substring')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 5, 10); + $expected = array('prefix:key', 5, 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsSubstring() + { + $redis = $this->getClient(); + + $redis->set('string', 'this is a string'); + + $this->assertSame('this', $redis->getrange('string', 0, 3)); + $this->assertSame('ing', $redis->getrange('string', -3, -1)); + $this->assertSame('this is a string', $redis->getrange('string', 0, -1)); + $this->assertSame('string', $redis->getrange('string', 10, 100)); + + $this->assertSame('t', $redis->getrange('string', 0, 0)); + $this->assertSame('', $redis->getrange('string', -1, 0)); + } + + /** + * @group connected + */ + public function testReturnsEmptyStringOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame('', $redis->getrange('string', 0, 3)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->getrange('metavars', 0, 5); + } +} diff --git a/tests/Predis/Commands/StringGetSetTest.php b/tests/Predis/Commands/StringGetSetTest.php new file mode 100644 index 00000000..e03ce1b4 --- /dev/null +++ b/tests/Predis/Commands/StringGetSetTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringGetSetTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringGetSet'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'GETSET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'value'); + $expected = array('key', 'value'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('value', $this->getCommand()->parseResponse('value')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsPreviousValueOfKey() + { + $redis = $this->getClient(); + + $this->assertNull($redis->getset('foo', 'bar')); + $this->assertSame('bar', $redis->getset('foo', 'barbar')); + + $redis->set('hoge', 'piyo'); + $this->assertSame('piyo', $redis->getset('hoge', 'piyopiyo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->getset('metavars', 'foo'); + } +} diff --git a/tests/Predis/Commands/StringGetTest.php b/tests/Predis/Commands/StringGetTest.php new file mode 100644 index 00000000..d9762907 --- /dev/null +++ b/tests/Predis/Commands/StringGetTest.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringGetTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringGet'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'GET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('foo'); + $expected = array('foo'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('bar', $this->getCommand()->parseResponse('bar')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsStringValue() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->set('foo', 'bar')); + $this->assertEquals('bar', $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsEmptyStringOnEmptyStrings() + { + $redis = $this->getClient(); + + $redis->set('foo', ''); + + $this->assertTrue($redis->exists('foo')); + $this->assertSame('', $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsNullOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertFalse($redis->exists('foo')); + $this->assertNull($redis->get('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->rpush('metavars', 'foo'); + $redis->get('metavars'); + } +} diff --git a/tests/Predis/Commands/StringIncrementByFloatTest.php b/tests/Predis/Commands/StringIncrementByFloatTest.php new file mode 100644 index 00000000..e1d7d876 --- /dev/null +++ b/tests/Predis/Commands/StringIncrementByFloatTest.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringIncrementByFloatTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringIncrementByFloat'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'INCRBYFLOAT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 5.0); + $expected = array('key', 5.0); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(5.0, $this->getCommand()->parseResponse(5.0)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 5.0); + $expected = array('prefix:key', 5.0); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertEquals(10.5, $redis->incrbyfloat('foo', 10.5)); + $this->assertEquals(10.5, $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsTheValueOfTheKeyAfterIncrement() + { + $redis = $this->getClient(); + + $redis->set('foo', 2); + + $this->assertEquals(22.123, $redis->incrbyfloat('foo', 20.123)); + $this->assertEquals(10, $redis->incrbyfloat('foo', -12.123)); + $this->assertEquals(-100.01, $redis->incrbyfloat('foo', -110.01)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not a valid float + */ + public function testThrowsExceptionOnDecrementValueNotFloat() + { + $redis = $this->getClient(); + + $redis->incrbyfloat('foo', 'bar'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not a valid float + */ + public function testThrowsExceptionOnKeyValueNotFloat() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->incrbyfloat('foo', 10.0); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->incrbyfloat('metavars', 10.0); + } +} diff --git a/tests/Predis/Commands/StringIncrementByTest.php b/tests/Predis/Commands/StringIncrementByTest.php new file mode 100644 index 00000000..1e03f4d7 --- /dev/null +++ b/tests/Predis/Commands/StringIncrementByTest.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringIncrementByTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringIncrementBy'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'INCRBY'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 5); + $expected = array('key', 5); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(5, $this->getCommand()->parseResponse(5)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 5); + $expected = array('prefix:key', 5); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(10, $redis->incrby('foo', 10)); + $this->assertEquals(10, $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsTheValueOfTheKeyAfterIncrement() + { + $redis = $this->getClient(); + + $redis->set('foo', 2); + + $this->assertSame(22, $redis->incrby('foo', 20)); + $this->assertSame(10, $redis->incrby('foo', -12)); + $this->assertSame(-100, $redis->incrby('foo', -110)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not an integer or out of range + */ + public function testThrowsExceptionOnDecrementValueNotInteger() + { + $redis = $this->getClient(); + + $redis->incrby('foo', 'bar'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not an integer or out of range + */ + public function testThrowsExceptionOnKeyValueNotInteger() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->incrby('foo', 10); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->incrby('metavars', 10); + } +} diff --git a/tests/Predis/Commands/StringIncrementTest.php b/tests/Predis/Commands/StringIncrementTest.php new file mode 100644 index 00000000..d8644f81 --- /dev/null +++ b/tests/Predis/Commands/StringIncrementTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringIncrementTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringIncrement'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'INCR'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(5, $this->getCommand()->parseResponse(5)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(1, $redis->incr('foo')); + $this->assertEquals(1, $redis->get('foo')); + } + + /** + * @group connected + */ + public function testReturnsTheValueOfTheKeyAfterIncrement() + { + $redis = $this->getClient(); + + $redis->set('foo', 2); + + $this->assertSame(3, $redis->incr('foo')); + $this->assertSame(4, $redis->incr('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->incr('metavars'); + } +} diff --git a/tests/Predis/Commands/StringPreciseSetExpireTest.php b/tests/Predis/Commands/StringPreciseSetExpireTest.php new file mode 100644 index 00000000..c464038a --- /dev/null +++ b/tests/Predis/Commands/StringPreciseSetExpireTest.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringPreciseSetExpireTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringPreciseSetExpire'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'PSETEX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 10, 'hello'); + $expected = array('key', 10, 'hello'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 10, 'hello'); + $expected = array('prefix:key', 10, 'hello'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyAndSetsTTL() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->psetex('foo', 10000, 'bar')); + $this->assertTrue($redis->exists('foo')); + $this->assertEquals(10, $redis->ttl('foo')); + } + + /** + * @group connected + * @group slow + */ + public function testKeyExpiresAfterTTL() + { + $redis = $this->getClient(); + + $redis->psetex('foo', 50, 'bar'); + $this->sleep(0.5); + $this->assertFalse($redis->exists('foo'));; + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not an integer or out of range + */ + public function testThrowsExceptionOnNonIntegerTTL() + { + $this->getClient()->psetex('foo', 2.5, 'bar'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR invalid expire time in SETEX + * @todo Should not Redis return PSETEX instead of SETEX here? + */ + public function testThrowsExceptionOnZeroTTL() + { + $this->getClient()->psetex('foo', 0, 'bar'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR invalid expire time in SETEX + * @todo Should not Redis return PSETEX instead of SETEX here? + */ + public function testThrowsExceptionOnNegativeTTL() + { + $this->getClient()->psetex('foo', -10000, 'bar'); + } +} diff --git a/tests/Predis/Commands/StringSetBitTest.php b/tests/Predis/Commands/StringSetBitTest.php new file mode 100644 index 00000000..6dfdaa57 --- /dev/null +++ b/tests/Predis/Commands/StringSetBitTest.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringSetBitTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringSetBit'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SETBIT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 7, 1); + $expected = array('key', 7, 1); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $command = $this->getCommand(); + $this->assertSame(0, $command->parseResponse(0)); + $this->assertSame(1, $command->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 7, 1); + $expected = array('prefix:key', 7, 1); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCanSetBitsOfStrings() + { + $redis = $this->getClient(); + + $redis->set('key:binary', "\x80\x00\00\x01"); + + $this->assertEquals(1, $redis->setbit('key:binary', 0, 0)); + $this->assertEquals(0, $redis->setbit('key:binary', 0, 0)); + $this->assertEquals("\x00\x00\00\x01", $redis->get('key:binary')); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->setbit('key:binary', 31, 1)); + $this->assertSame(0, $redis->setbit('key:binary', 0, 1)); + $this->assertSame(4, $redis->strlen('key:binary')); + $this->assertSame("\x80\x00\00\x01", $redis->get('key:binary')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR bit is not an integer or out of range + */ + public function testThrowsExceptionOnInvalidBitValue() + { + $redis = $this->getClient()->setbit('key:binary', 10, 255); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR bit offset is not an integer or out of range + */ + public function testThrowsExceptionOnNegativeOffset() + { + $redis = $this->getClient()->setbit('key:binary', -1, 1); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR bit offset is not an integer or out of range + */ + public function testThrowsExceptionOnInvalidOffset() + { + $redis = $this->getClient()->setbit('key:binary', 'invalid', 1); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->setbit('metavars', 0, 1); + } +} diff --git a/tests/Predis/Commands/StringSetExpireTest.php b/tests/Predis/Commands/StringSetExpireTest.php new file mode 100644 index 00000000..3fae15aa --- /dev/null +++ b/tests/Predis/Commands/StringSetExpireTest.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringSetExpireTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringSetExpire'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SETEX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 10, 'hello'); + $expected = array('key', 10, 'hello'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 10, 'hello'); + $expected = array('prefix:key', 10, 'hello'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyAndSetsTTL() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->setex('foo', 10, 'bar')); + $this->assertTrue($redis->exists('foo')); + $this->assertEquals(10, $redis->ttl('foo')); + } + + /** + * @group connected + * @group slow + */ + public function testKeyExpiresAfterTTL() + { + $redis = $this->getClient(); + + $redis->setex('foo', 1, 'bar'); + $this->sleep(2.0); + $this->assertFalse($redis->exists('foo'));; + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR value is not an integer or out of range + */ + public function testThrowsExceptionOnNonIntegerTTL() + { + $this->getClient()->setex('foo', 2.5, 'bar'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR invalid expire time in SETEX + */ + public function testThrowsExceptionOnZeroTTL() + { + $this->getClient()->setex('foo', 0, 'bar'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR invalid expire time in SETEX + */ + public function testThrowsExceptionOnNegativeTTL() + { + $this->getClient()->setex('foo', -10, 'bar'); + } +} diff --git a/tests/Predis/Commands/StringSetMultiplePreserveTest.php b/tests/Predis/Commands/StringSetMultiplePreserveTest.php new file mode 100644 index 00000000..b2fee1c4 --- /dev/null +++ b/tests/Predis/Commands/StringSetMultiplePreserveTest.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringSetMultiplePreserveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringSetMultiplePreserve'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'MSETNX'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('foo', 'bar', 'hoge', 'piyo'); + $expected = array('foo', 'bar', 'hoge', 'piyo'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleNamedArray() + { + $arguments = array(array('foo' => 'bar', 'hoge' => 'piyo')); + $expected = array('foo', 'bar', 'hoge', 'piyo'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(true, $this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('foo', 'bar', 'hoge', 'piyo'); + $expected = array('prefix:foo', 'bar', 'prefix:hoge', 'piyo'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesMultipleKeys() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->msetnx('foo', 'bar', 'hoge', 'piyo')); + $this->assertSame('bar', $redis->get('foo')); + $this->assertSame('piyo', $redis->get('hoge')); + } + + /** + * @group connected + */ + public function testCreatesMultipleKeysAndPreservesExistingOnes() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + + $this->assertFalse($redis->msetnx('foo', 'barbar', 'hoge', 'piyo')); + $this->assertSame('bar', $redis->get('foo')); + $this->assertFalse($redis->exists('hoge')); + } +} diff --git a/tests/Predis/Commands/StringSetMultipleTest.php b/tests/Predis/Commands/StringSetMultipleTest.php new file mode 100644 index 00000000..4893aa0e --- /dev/null +++ b/tests/Predis/Commands/StringSetMultipleTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringSetMultipleTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringSetMultiple'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'MSET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('foo', 'bar', 'hoge', 'piyo'); + $expected = array('foo', 'bar', 'hoge', 'piyo'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleNamedArray() + { + $arguments = array(array('foo' => 'bar', 'hoge' => 'piyo')); + $expected = array('foo', 'bar', 'hoge', 'piyo'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(true, $this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('foo', 'bar', 'hoge', 'piyo'); + $expected = array('prefix:foo', 'bar', 'prefix:hoge', 'piyo'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesMultipleKeys() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->mset('foo', 'bar', 'hoge', 'piyo')); + $this->assertSame('bar', $redis->get('foo')); + $this->assertSame('piyo', $redis->get('hoge')); + } +} diff --git a/tests/Predis/Commands/StringSetRangeTest.php b/tests/Predis/Commands/StringSetRangeTest.php new file mode 100644 index 00000000..e07c4766 --- /dev/null +++ b/tests/Predis/Commands/StringSetRangeTest.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringSetRangeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringSetRange'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SETRANGE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 5, 'range'); + $expected = array('key', 5, 'range'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(10, $this->getCommand()->parseResponse(10)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 5, 'range'); + $expected = array('prefix:key', 5, 'range'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testCreatesNewKeyOnNonExistingKey() + { + $redis = $this->getClient(); + + $this->assertSame(3, $redis->setrange('foo', 0, 'bar')); + $this->assertSame('bar', $redis->get('foo')); + + $this->assertSame(8, $redis->setrange('hoge', 4, 'piyo')); + $this->assertSame("\x00\x00\x00\x00piyo", $redis->get('hoge')); + } + + /** + * @group connected + */ + public function testOverwritesOrAppendBytesInKeys() + { + $redis = $this->getClient(); + + $redis->set('foo', 'barbar'); + + $this->assertSame(6, $redis->setrange('foo', 3, 'baz')); + $this->assertSame('barbaz', $redis->get('foo')); + + $this->assertEquals(16, $redis->setrange('foo', 10, 'foofoo')); + $this->assertEquals("barbaz\x00\x00\x00\x00foofoo", $redis->get('foo')); + } + + /** + * @group connected + */ + public function testHandlesBinaryData() + { + $redis = $this->getClient(); + + $this->assertSame(4, $redis->setrange('key:binary', 0, pack('i', -2147483648))); + + list($unpacked) = array_values(unpack('i', $redis->get('key:binary'))); + $this->assertEquals(-2147483648, $unpacked); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR offset is out of range + */ + public function testThrowsExceptionOnInvalidOffset() + { + $this->getClient()->setrange('var', -1, 'bogus'); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->setrange('metavars', 3, 'bar'); + } +} diff --git a/tests/Predis/Commands/StringSetTest.php b/tests/Predis/Commands/StringSetTest.php new file mode 100644 index 00000000..70c70293 --- /dev/null +++ b/tests/Predis/Commands/StringSetTest.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringSetTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringSet'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SET'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('foo', 'bar'); + $expected = array('foo', 'bar'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'value'); + $expected = array('prefix:key', 'value'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testSetStringValue() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->set('foo', 'bar')); + $this->assertTrue($redis->exists('foo')); + $this->assertEquals('bar', $redis->get('foo')); + } +} diff --git a/tests/Predis/Commands/StringStrlenTest.php b/tests/Predis/Commands/StringStrlenTest.php new file mode 100644 index 00000000..032563f7 --- /dev/null +++ b/tests/Predis/Commands/StringStrlenTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-string + */ +class StringStrlenTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringStrlen'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'STRLEN'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(4, $this->getCommand()->parseResponse(4)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsTheLengthOfString() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $this->assertSame(3, $redis->strlen('foo')); + + $redis->append('foo', 'bar'); + $this->assertSame(6, $redis->strlen('foo')); + } + + /** + * @group connected + */ + public function testReturnsZeroOnNonExistingKeys() + { + $redis = $this->getClient(); + + $this->assertSame(0, $redis->strlen('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->lpush('metavars', 'foo'); + $redis->strlen('metavars'); + } +} diff --git a/tests/Predis/Commands/StringSubstrTest.php b/tests/Predis/Commands/StringSubstrTest.php new file mode 100644 index 00000000..4831dcbb --- /dev/null +++ b/tests/Predis/Commands/StringSubstrTest.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * SUBSTR is actually the old name of GETRANGE in version of Redis <= 2.0. + * This command should be considered obsolete and we will perform any kind + * of tests against a Redis server for this one. + * + * @group commands + * @group realm-string + */ +class StringSubstrTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\StringSubstr'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'SUBSTR'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 5, 10); + $expected = array('key', 5, 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('substring',$this->getCommand()->parseResponse('substring')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 5, 10); + $expected = array('prefix:key', 5, 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } +} diff --git a/tests/Predis/Commands/TransactionDiscardTest.php b/tests/Predis/Commands/TransactionDiscardTest.php new file mode 100644 index 00000000..84bd8590 --- /dev/null +++ b/tests/Predis/Commands/TransactionDiscardTest.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-transaction + */ +class TransactionDiscardTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\TransactionDiscard'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'DISCARD'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group connected + */ + public function testAbortsTransactionAndRestoresNormalFlow() + { + $redis = $this->getClient(); + + $redis->multi(); + + $this->assertInstanceOf('Predis\ResponseQueued', $redis->set('foo', 'bar')); + $this->assertTrue($redis->discard()); + $this->assertFalse($redis->exists('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR DISCARD without MULTI + */ + public function testThrowsExceptionWhenCallingOutsideTransaction() + { + $redis = $this->getClient(); + + $redis->discard(); + } +} diff --git a/tests/Predis/Commands/TransactionExecTest.php b/tests/Predis/Commands/TransactionExecTest.php new file mode 100644 index 00000000..75e8c46e --- /dev/null +++ b/tests/Predis/Commands/TransactionExecTest.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-transaction + */ +class TransactionExecTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\TransactionExec'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'EXEC'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('tx1', 'tx2'); + $expected = array('tx1', 'tx2'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group connected + */ + public function testExecutesTransactionAndReturnsArrayOfReplies() + { + $redis = $this->getClient(); + + $redis->multi(); + $redis->echo('tx1'); + $redis->echo('tx2'); + + $this->assertSame(array('tx1', 'tx2'), $redis->exec()); + } + + /** + * @group connected + */ + public function testReturnsEmptyArrayOnEmptyTransactions() + { + $redis = $this->getClient(); + + $redis->multi(); + + $this->assertSame(array(), $redis->exec()); + } + + /** + * @group connected + */ + public function testRepliesOfTransactionsAreNotParsed() + { + $redis = $this->getClient(); + + $redis->multi(); + $redis->ping(); + $redis->set('foo', 'bar'); + $redis->exists('foo'); + + $this->assertSame(array('PONG', true, 1), $redis->exec()); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR EXEC without MULTI + */ + public function testThrowsExceptionWhenCallingOutsideTransaction() + { + $redis = $this->getClient(); + + $redis->exec(); + } +} diff --git a/tests/Predis/Commands/TransactionMultiTest.php b/tests/Predis/Commands/TransactionMultiTest.php new file mode 100644 index 00000000..ad818f48 --- /dev/null +++ b/tests/Predis/Commands/TransactionMultiTest.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-transaction + */ +class TransactionMultiTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\TransactionMulti'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'MULTI'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group connected + */ + public function testInitializesNewTransaction() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->multi()); + $this->assertSame('QUEUED', (string) $redis->echo('tx1')); + $this->assertSame('QUEUED', (string) $redis->echo('tx2')); + } + + /** + * @group connected + */ + public function testActuallyReturnsReplyObjectAbstraction() + { + $redis = $this->getClient(); + + $this->assertTrue($redis->multi()); + $this->assertInstanceOf('Predis\IReplyObject', $redis->echo('tx1')); + $this->assertInstanceOf('Predis\ResponseQueued', $redis->echo('tx2')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR MULTI calls can not be nested + */ + public function testThrowsExceptionWhenCallingMultiInsideTransaction() + { + $redis = $this->getClient(); + + $redis->multi(); + $redis->multi(); + } +} diff --git a/tests/Predis/Commands/TransactionUnwatchTest.php b/tests/Predis/Commands/TransactionUnwatchTest.php new file mode 100644 index 00000000..85393caa --- /dev/null +++ b/tests/Predis/Commands/TransactionUnwatchTest.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-transaction + */ +class TransactionUnwatchTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\TransactionUnwatch'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'UNWATCH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $command = $this->getCommand(); + $command->setArguments(array()); + + $this->assertSame(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group connected + */ + public function testUnwatchWatchedKeys() + { + $redis1 = $this->getClient(); + $redis2 = $this->getClient(); + + $redis1->set('foo', 'bar'); + $redis1->watch('foo'); + $this->assertTrue($redis1->unwatch()); + $redis1->multi(); + $redis1->get('foo'); + + $redis2->set('foo', 'hijacked'); + + $this->assertSame(array('hijacked'), $redis1->exec()); + } + + /** + * @group connected + */ + public function testCanBeCalledInsideTransaction() + { + $redis = $this->getClient(); + + $redis->multi(); + $this->assertInstanceOf('Predis\ResponseQueued', $redis->unwatch()); + } +} diff --git a/tests/Predis/Commands/TransactionWatchTest.php b/tests/Predis/Commands/TransactionWatchTest.php new file mode 100644 index 00000000..33f6f1f1 --- /dev/null +++ b/tests/Predis/Commands/TransactionWatchTest.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-transaction + */ +class TransactionWatchTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\TransactionWatch'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'WATCH'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsAsSingleArray() + { + $arguments = array(array('key1', 'key2', 'key3')); + $expected = array('key1', 'key2', 'key3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertTrue($this->getCommand()->parseResponse(true)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key1', 'key2', 'key3'); + $expected = array('prefix:key1', 'prefix:key2', 'prefix:key3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testAbortsTransactionOnExternalWriteOperations() + { + $redis1 = $this->getClient(); + $redis2 = $this->getClient(); + + $redis1->mset('foo', 'bar', 'hoge', 'piyo'); + + $this->assertTrue($redis1->watch('foo', 'hoge')); + $this->assertTrue($redis1->multi()); + $this->assertInstanceOf('Predis\ResponseQueued', $redis1->get('foo')); + $this->assertTrue($redis2->set('foo', 'hijacked')); + $this->assertNull($redis1->exec()); + $this->assertSame('hijacked', $redis1->get('foo')); + } + + /** + * @group connected + */ + public function testCanWatchNotYetExistingKeys() + { + $redis1 = $this->getClient(); + $redis2 = $this->getClient(); + + $this->assertTrue($redis1->watch('foo')); + $this->assertTrue($redis1->multi()); + $this->assertInstanceOf('Predis\ResponseQueued', $redis1->set('foo', 'bar')); + $this->assertTrue($redis2->set('foo', 'hijacked')); + $this->assertNull($redis1->exec()); + $this->assertSame('hijacked', $redis1->get('foo')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR WATCH inside MULTI is not allowed + */ + public function testThrowsExceptionWhenCallingInsideTransaction() + { + $redis = $this->getClient(); + + $redis->multi(); + $redis->watch('foo'); + } +} diff --git a/tests/Predis/Commands/ZSetAddTest.php b/tests/Predis/Commands/ZSetAddTest.php new file mode 100644 index 00000000..c94ceb29 --- /dev/null +++ b/tests/Predis/Commands/ZSetAddTest.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetAddTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetAdd'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZADD'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 1, 'member1', 2, 'member2'); + $expected = array('key', 1, 'member1', 2, 'member2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsMembersScoresAsSingleArray() + { + $arguments = array('key', array('member1' => 1, 'member2' => 2)); + $expected = array('key', 1, 'member1', 2, 'member2'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'score1', 'member1', 'score2', 'member2'); + $expected = array('prefix:key', 'score1', 'member1', 'score2', 'member2'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testAddsOrUpdatesMembersOrderingByScore() + { + $redis = $this->getClient(); + + $this->assertSame(5, $redis->zadd('letters', 1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e')); + $this->assertSame(array('a', 'b', 'c', 'd', 'e'), $redis->zrange('letters', 0, -1)); + + $this->assertSame(1, $redis->zadd('letters', 1, 'e', 8, 'c', 6, 'f')); + $this->assertSame(array('a', 'e', 'b', 'd', 'f', 'c'), $redis->zrange('letters', 0, -1)); + } + + /** + * @group connected + */ + public function testAcceptsFloatValuesAsScore() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 0.2, 'b', 0.3, 'a', 0.1, 'c'); + $this->assertSame(array('c', 'b', 'a'), $redis->zrange('letters', 0, -1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zadd('foo', 10, 'bar'); + } +} diff --git a/tests/Predis/Commands/ZSetCardinalityTest.php b/tests/Predis/Commands/ZSetCardinalityTest.php new file mode 100644 index 00000000..40bb8f2e --- /dev/null +++ b/tests/Predis/Commands/ZSetCardinalityTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetCardinalityTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetCardinality'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZCARD'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key'); + $expected = array('key'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key'); + $expected = array('prefix:key'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsSizeOfSortedSet() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 1, 'a', 2, 'b', 3, 'c'); + $this->assertSame(3, $redis->zcard('letters')); + + $this->assertSame(0, $redis->zcard('unknown')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zcard('foo'); + } +} diff --git a/tests/Predis/Commands/ZSetCountTest.php b/tests/Predis/Commands/ZSetCountTest.php new file mode 100644 index 00000000..db548696 --- /dev/null +++ b/tests/Predis/Commands/ZSetCountTest.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetCountTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetCount'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZCOUNT'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 0, 10); + $expected = array('key', 0, 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 0, 10); + $expected = array('prefix:key', 0, 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsNumberOfElementsInGivenScoreRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 10, 'a', 20, 'b', 30, 'c', 40, 'd', 50, 'e'); + + $this->assertSame(5, $redis->zcount('letters', 0, 100)); + $this->assertSame(5, $redis->zcount('letters', -100, 100)); + $this->assertSame(2, $redis->zcount('letters', 25, 45)); + $this->assertSame(1, $redis->zcount('letters', 20, 20)); + $this->assertSame(0, $redis->zcount('letters', 0, 0)); + + $this->assertSame(0, $redis->zcount('unknown', 0, 100)); + } + + /** + * @group connected + */ + public function testInfinityScoreIntervals() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 10, 'a', 20, 'b', 30, 'c', 40, 'd', 50, 'e'); + + $this->assertSame(3, $redis->zcount('letters', '-inf', 30)); + $this->assertSame(3, $redis->zcount('letters', 30, '+inf')); + $this->assertSame(5, $redis->zcount('letters', '-inf', '+inf')); + } + + /** + * @group connected + */ + public function testExclusiveScoreIntervals() + { + $redis = $this->getClient(); + + $redis->zadd('letters', 10, 'a', 20, 'b', 30, 'c', 40, 'd', 50, 'e'); + + $this->assertSame(2, $redis->zcount('letters', 10, '(30')); + $this->assertSame(2, $redis->zcount('letters', '(10', 30)); + $this->assertSame(1, $redis->zcount('letters', '(10', '(30')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zcount('foo', 0, 10); + } +} diff --git a/tests/Predis/Commands/ZSetIncrementByTest.php b/tests/Predis/Commands/ZSetIncrementByTest.php new file mode 100644 index 00000000..1994a23d --- /dev/null +++ b/tests/Predis/Commands/ZSetIncrementByTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetIncrementByTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetIncrementBy'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZINCRBY'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 1.0, 'member'); + $expected = array('key', 1.0, 'member'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame('1', $this->getCommand()->parseResponse('1')); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 1.0, 'member'); + $expected = array('prefix:key', 1.0, 'member'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testIncrementsScoreOfMemberByFloat() + { + $redis = $this->getClient(); + + $this->assertSame('1', $redis->zincrby('letters', 1, 'member')); + $this->assertSame('0', $redis->zincrby('letters', -1, 'member')); + $this->assertSame('0.5', $redis->zincrby('letters', 0.5, 'member')); + $this->assertSame('-10', $redis->zincrby('letters', -10.5, 'member')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zincrby('foo', 1, 'bar'); + } +} diff --git a/tests/Predis/Commands/ZSetIntersectionStoreTest.php b/tests/Predis/Commands/ZSetIntersectionStoreTest.php new file mode 100644 index 00000000..3d6c4c07 --- /dev/null +++ b/tests/Predis/Commands/ZSetIntersectionStoreTest.php @@ -0,0 +1,193 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetIntersectionStoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetIntersectionStore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZINTERSTORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $modifiers = array( + 'aggregate' => 'sum', + 'weights' => array(10, 100), + ); + $arguments = array('zset:destination', 2, 'zset1', 'zset2', $modifiers); + + $expected = array( + 'zset:destination', 2, 'zset1', 'zset2', 'WEIGHTS', 10, 100, 'AGGREGATE', 'sum' + ); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsSourceKeysAsSingleArray() + { + $modifiers = array( + 'aggregate' => 'sum', + 'weights' => array(10, 100), + ); + $arguments = array('zset:destination', array('zset1', 'zset2'), $modifiers); + + $expected = array( + 'zset:destination', 2, 'zset1', 'zset2', 'WEIGHTS', 10, 100, 'AGGREGATE', 'sum' + ); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $modifiers = array( + 'aggregate' => 'sum', + 'weights' => array(10, 100), + ); + $arguments = array('zset:destination', 2, 'zset1', 'zset2', $modifiers); + + $expected = array( + 'prefix:zset:destination', 2, 'prefix:zset1', 'prefix:zset2', 'WEIGHTS', 10, 100, 'AGGREGATE', 'sum' + ); + + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testStoresIntersectionInNewSortedSet() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $this->assertSame(2, $redis->zinterstore('letters:out', 2, 'letters:1st', 'letters:2nd')); + $this->assertSame(array(array('b', '3'), array('c', '5')), $redis->zrange('letters:out', 0, -1, 'withscores')); + + $this->assertSame(0, $redis->zinterstore('letters:out', 2, 'letters:1st', 'letters:void')); + $this->assertSame(0, $redis->zinterstore('letters:out', 2, 'letters:void', 'letters:2nd')); + $this->assertSame(0, $redis->zinterstore('letters:out', 2, 'letters:void', 'letters:void')); + } + + /** + * @group connected + */ + public function testStoresIntersectionWithAggregateModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $options = array('aggregate' => 'min'); + $this->assertSame(2, $redis->zinterstore('letters:min', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame(array(array('b', '1'), array('c', '2')), $redis->zrange('letters:min', 0, -1, 'withscores')); + + $options = array('aggregate' => 'max'); + $this->assertSame(2, $redis->zinterstore('letters:max', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame(array(array('b', '2'), array('c', '3')), $redis->zrange('letters:max', 0, -1, 'withscores')); + + $options = array('aggregate' => 'sum'); + $this->assertSame(2, $redis->zinterstore('letters:sum', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame(array(array('b', '3'), array('c', '5')), $redis->zrange('letters:sum', 0, -1, 'withscores')); + } + + /** + * @group connected + */ + public function testStoresIntersectionWithWeightsModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $options = array('weights' => array(2, 3)); + $this->assertSame(2, $redis->zinterstore('letters:out', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame(array(array('b', '7'), array('c', '12')), $redis->zrange('letters:out', 0, -1, 'withscores')); + } + + /** + * @group connected + */ + public function testStoresIntersectionWithCombinedModifiers() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $options = array('aggregate' => 'max', 'weights' => array(10, 15)); + $this->assertSame(2, $redis->zinterstore('letters:out', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame(array(array('b', '20'), array('c', '30')), $redis->zrange('letters:out', 0, -1, 'withscores')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zinterstore('zset:destination', 1, 'foo'); + } +} diff --git a/tests/Predis/Commands/ZSetRangeByScoreTest.php b/tests/Predis/Commands/ZSetRangeByScoreTest.php new file mode 100644 index 00000000..1ed193f7 --- /dev/null +++ b/tests/Predis/Commands/ZSetRangeByScoreTest.php @@ -0,0 +1,230 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetRangeByScoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetRangeByScore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZRANGEBYSCORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $modifiers = array( + 'withscores' => true, + 'limit' => array(0, 100), + ); + + $arguments = array('zset', 0, 100, $modifiers); + $expected = array('zset', 0, 100, 'LIMIT', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsWithStringWithscores() + { + $arguments = array('zset', 0, 100, 'withscores'); + $expected = array('zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsWithNamedLimit() + { + $arguments = array('zset', 0, 100, array('limit' => array('offset' => 1, 'count' => 2))); + $expected = array('zset', 0, 100, 'LIMIT', 1, 2); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('element1', 'element2', 'element3'); + $expected = array('element1', 'element2', 'element3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testParseResponseWithScores() + { + $raw = array('element1', '1', 'element2', '2', 'element3', '3'); + $expected = array(array('element1', '1'), array('element2', '2'), array('element3', '3')); + + $command = $this->getCommandWithArgumentsArray(array('zset', 0, 1, 'withscores')); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $modifiers = array( + 'withscores' => true, + 'limit' => array(0, 100), + ); + + $arguments = array('zset', 0, 100, $modifiers); + $expected = array('prefix:zset', 0, 100, 'LIMIT', 0, 100, 'WITHSCORES'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsElementsInScoreRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array('a'), $redis->zrangebyscore('letters', -10, -10)); + $this->assertSame(array('c', 'd', 'e', 'f'), $redis->zrangebyscore('letters', 10, 30)); + $this->assertSame(array('d', 'e'), $redis->zrangebyscore('letters', 20, 20)); + $this->assertSame(array(), $redis->zrangebyscore('letters', 30, 0)); + + $this->assertSame(array(), $redis->zrangebyscore('unknown', 0, 30)); + } + + /** + * @group connected + */ + public function testInfinityScoreIntervals() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array('a', 'b', 'c'), $redis->zrangebyscore('letters', '-inf', 15)); + $this->assertSame(array('d', 'e', 'f'), $redis->zrangebyscore('letters', 15, '+inf')); + $this->assertSame(array('a', 'b', 'c', 'd', 'e', 'f'), $redis->zrangebyscore('letters', '-inf', '+inf')); + } + + /** + * @group connected + */ + public function testExclusiveScoreIntervals() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array('c', 'd', 'e'), $redis->zrangebyscore('letters', 10, '(30')); + $this->assertSame(array('d', 'e', 'f'), $redis->zrangebyscore('letters', '(10', 30)); + $this->assertSame(array('d', 'e'), $redis->zrangebyscore('letters', '(10', '(30')); + } + + /** + * @group connected + */ + public function testRangeWithWithscoresModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + $expected = array(array('c', '10'), array('d', '20'), array('e', '20')); + + $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, 'withscores')); + $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, array('withscores' => true))); + } + + /** + * @group connected + */ + public function testRangeWithLimitModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + $expected = array('d', 'e'); + + $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, array('limit' => array(1, 2)))); + $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, array('limit' => array('offset' => 1, 'count' => 2)))); + } + + /** + * @group connected + */ + public function testRangeWithCombinedModifiers() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $options = array('limit' => array(1, 2), 'withscores' => true); + $expected = array(array('d', '20'), array('e', '20')); + + $this->assertSame($expected, $redis->zrangebyscore('letters', 10, 20, $options)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrangebyscore('foo', 0, 10); + } +} diff --git a/tests/Predis/Commands/ZSetRangeTest.php b/tests/Predis/Commands/ZSetRangeTest.php new file mode 100644 index 00000000..e92e064e --- /dev/null +++ b/tests/Predis/Commands/ZSetRangeTest.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetRangeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetRange'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZRANGE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('zset', 0, 100, array('withscores' => true)); + $expected = array('zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsWithStringWithscores() + { + $arguments = array('zset', 0, 100, 'withscores'); + $expected = array('zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('element1', 'element2', 'element3'); + $expected = array('element1', 'element2', 'element3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testParseResponseWithScores() + { + $raw = array('element1', '1', 'element2', '2', 'element3', '3'); + $expected = array(array('element1', '1'), array('element2', '2'), array('element3', '3')); + + $command = $this->getCommandWithArgumentsArray(array('zset', 0, 1, 'withscores')); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('zset', 0, 100, array('withscores' => true)); + $expected = array('prefix:zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsElementsInRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array(), $redis->zrange('letters', 1, 0)); + $this->assertSame(array('a'), $redis->zrange('letters', 0, 0)); + $this->assertSame(array('a', 'b', 'c', 'd'), $redis->zrange('letters', 0, 3)); + + $this->assertSame(array('a', 'b', 'c', 'd', 'e', 'f'), $redis->zrange('letters', 0, -1)); + $this->assertSame(array('a', 'b', 'c'), $redis->zrange('letters', 0, -4)); + $this->assertSame(array('c'), $redis->zrange('letters', 2, -4)); + $this->assertSame(array('a', 'b', 'c', 'd', 'e', 'f'), $redis->zrange('letters', -100, 100)); + + $this->assertSame(array(), $redis->zrange('unknown', 0, 30)); + } + + /** + * @group connected + */ + public function testRangeWithWithscoresModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + $expected = array(array('c', '10'), array('d', '20'), array('e', '20')); + + $this->assertSame($expected, $redis->zrange('letters', 2, 4, 'withscores')); + $this->assertSame($expected, $redis->zrange('letters', 2, 4, array('withscores' => true))); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrange('foo', 0, 10); + } +} diff --git a/tests/Predis/Commands/ZSetRankTest.php b/tests/Predis/Commands/ZSetRankTest.php new file mode 100644 index 00000000..add3652d --- /dev/null +++ b/tests/Predis/Commands/ZSetRankTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetRankTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetRank'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZRANK'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'member'); + $expected = array('key', 'member'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'member'); + $expected = array('prefix:key', 'member'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsRank() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(0, $redis->zrank('letters', 'a')); + $this->assertSame(1, $redis->zrank('letters', 'b')); + $this->assertSame(4, $redis->zrank('letters', 'e')); + + $this->assertNull($redis->zrank('unknown', 'a')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrank('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/ZSetRemoveRangeByRankTest.php b/tests/Predis/Commands/ZSetRemoveRangeByRankTest.php new file mode 100644 index 00000000..18109e3e --- /dev/null +++ b/tests/Predis/Commands/ZSetRemoveRangeByRankTest.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetRemoveRangeByRankTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetRemoveRangeByRank'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZREMRANGEBYRANK'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 0, 10); + $expected = array('key', 0, 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 0, 10); + $expected = array('prefix:key', 0, 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRemovesRangeByRank() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(3, $redis->zremrangebyrank('letters', 2, 4)); + $this->assertSame(array('a', 'b', 'f'), $redis->zrange('letters', 0, -1)); + + $this->assertSame(0, $redis->zremrangebyrank('unknown', 0, 30)); + } + + /** + * @group connected + */ + public function testRemovesRangeByRankWithNegativeIndex() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(3, $redis->zremrangebyrank('letters', -5, 3)); + $this->assertSame(array('a', 'e', 'f'), $redis->zrange('letters', 0, -1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zremrangebyrank('foo', 0, 10); + } +} diff --git a/tests/Predis/Commands/ZSetRemoveRangeByScoreTest.php b/tests/Predis/Commands/ZSetRemoveRangeByScoreTest.php new file mode 100644 index 00000000..35edef39 --- /dev/null +++ b/tests/Predis/Commands/ZSetRemoveRangeByScoreTest.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetRemoveRangeByScoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetRemoveRangeByScore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZREMRANGEBYSCORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 0, 10); + $expected = array('key', 0, 10); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 0, 10); + $expected = array('prefix:key', 0, 10); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRemovesRangeByScore() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(3, $redis->zremrangebyscore('letters', 5, 20)); + $this->assertSame(array('a', 'b', 'f'), $redis->zrange('letters', 0, -1)); + + $this->assertSame(0, $redis->zremrangebyscore('unknown', 0, 30)); + } + + /** + * @group connected + */ + public function testRemovesRangeByExclusiveScore() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(2, $redis->zremrangebyscore('letters', '(10', '(30')); + $this->assertSame(array('a', 'b', 'c', 'f'), $redis->zrange('letters', 0, -1)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zremrangebyscore('foo', 0, 10); + } +} diff --git a/tests/Predis/Commands/ZSetRemoveTest.php b/tests/Predis/Commands/ZSetRemoveTest.php new file mode 100644 index 00000000..3660bda0 --- /dev/null +++ b/tests/Predis/Commands/ZSetRemoveTest.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetRemoveTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetRemove'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZREM'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('zset', 'member1', 'member2', 'member3'); + $expected = array('zset', 'member1', 'member2', 'member3'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('zset', 'member1', 'member2', 'member3'); + $expected = array('prefix:zset', 'member1', 'member2', 'member3'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testRemovesSpecifiedMembers() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(3, $redis->zrem('letters', 'b', 'd', 'f', 'z')); + $this->assertSame(array('a', 'c', 'e'), $redis->zrange('letters', 0, -1)); + + $this->assertSame(0, $redis->zrem('unknown', 'a')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrem('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/ZSetReverseRangeByScoreTest.php b/tests/Predis/Commands/ZSetReverseRangeByScoreTest.php new file mode 100644 index 00000000..e9415191 --- /dev/null +++ b/tests/Predis/Commands/ZSetReverseRangeByScoreTest.php @@ -0,0 +1,230 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetReverseRangeByScoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetReverseRangeByScore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZREVRANGEBYSCORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $modifiers = array( + 'withscores' => true, + 'limit' => array(0, 100), + ); + + $arguments = array('zset', 0, 100, $modifiers); + $expected = array('zset', 0, 100, 'LIMIT', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsWithStringWithscores() + { + $arguments = array('zset', 0, 100, 'withscores'); + $expected = array('zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsWithNamedLimit() + { + $arguments = array('zset', 0, 100, array('limit' => array('offset' => 1, 'count' => 2))); + $expected = array('zset', 0, 100, 'LIMIT', 1, 2); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('element1', 'element2', 'element3'); + $expected = array('element1', 'element2', 'element3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testParseResponseWithScores() + { + $raw = array('element1', '1', 'element2', '2', 'element3', '3'); + $expected = array(array('element1', '1'), array('element2', '2'), array('element3', '3')); + + $command = $this->getCommandWithArgumentsArray(array('zset', 0, 1, 'withscores')); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $modifiers = array( + 'withscores' => true, + 'limit' => array(0, 100), + ); + + $arguments = array('zset', 0, 100, $modifiers); + $expected = array('prefix:zset', 0, 100, 'LIMIT', 0, 100, 'WITHSCORES'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsElementsInScoreRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array('a'), $redis->zrevrangebyscore('letters', -10, -10)); + $this->assertSame(array(), $redis->zrevrangebyscore('letters', 10, 30)); + $this->assertSame(array('e', 'd'), $redis->zrevrangebyscore('letters', 20, 20)); + $this->assertSame(array('f', 'e', 'd', 'c', 'b'), $redis->zrevrangebyscore('letters', 30, 0)); + + $this->assertSame(array(), $redis->zrevrangebyscore('unknown', 0, 30)); + } + + /** + * @group connected + */ + public function testInfinityScoreIntervals() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array('f', 'e', 'd'), $redis->zrevrangebyscore('letters', '+inf', 15)); + $this->assertSame(array('c', 'b', 'a'), $redis->zrevrangebyscore('letters', 15, '-inf')); + $this->assertSame(array('f', 'e', 'd', 'c', 'b', 'a'), $redis->zrevrangebyscore('letters', '+inf', '-inf')); + } + + /** + * @group connected + */ + public function testExclusiveScoreIntervals() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array('e', 'd', 'c'), $redis->zrevrangebyscore('letters', '(30', 10)); + $this->assertSame(array('f', 'e', 'd'), $redis->zrevrangebyscore('letters', 30, '(10')); + $this->assertSame(array('e', 'd'), $redis->zrevrangebyscore('letters', '(30', '(10')); + } + + /** + * @group connected + */ + public function testRangeWithWithscoresModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + $expected = array(array('e', '20'), array('d', '20'), array('c', '10')); + + $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, 'withscores')); + $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, array('withscores' => true))); + } + + /** + * @group connected + */ + public function testRangeWithLimitModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + $expected = array('d', 'c'); + + $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, array('limit' => array(1, 2)))); + $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, array('limit' => array('offset' => 1, 'count' => 2)))); + } + + /** + * @group connected + */ + public function testRangeWithCombinedModifiers() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $options = array('limit' => array(1, 2), 'withscores' => true); + $expected = array(array('d', '20'), array('c', '10')); + + $this->assertSame($expected, $redis->zrevrangebyscore('letters', 20, 10, $options)); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrevrangebyscore('foo', 0, 10); + } +} diff --git a/tests/Predis/Commands/ZSetReverseRangeTest.php b/tests/Predis/Commands/ZSetReverseRangeTest.php new file mode 100644 index 00000000..6304b117 --- /dev/null +++ b/tests/Predis/Commands/ZSetReverseRangeTest.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetReverseRangeTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetReverseRange'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZREVRANGE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('zset', 0, 100, array('withscores' => true)); + $expected = array('zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsWithStringWithscores() + { + $arguments = array('zset', 0, 100, 'withscores'); + $expected = array('zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $raw = array('element1', 'element2', 'element3'); + $expected = array('element1', 'element2', 'element3'); + + $command = $this->getCommand(); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testParseResponseWithScores() + { + $raw = array('element1', '1', 'element2', '2', 'element3', '3'); + $expected = array(array('element1', '1'), array('element2', '2'), array('element3', '3')); + + $command = $this->getCommandWithArgumentsArray(array('zset', 0, 1, 'withscores')); + + $this->assertSame($expected, $command->parseResponse($raw)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('zset', 0, 100, array('withscores' => true)); + $expected = array('prefix:zset', 0, 100, 'WITHSCORES'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsElementsInRange() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(array(), $redis->zrevrange('letters', 1, 0)); + $this->assertSame(array('f'), $redis->zrevrange('letters', 0, 0)); + $this->assertSame(array('f', 'e', 'd', 'c'), $redis->zrevrange('letters', 0, 3)); + + $this->assertSame(array('f', 'e', 'd', 'c', 'b', 'a'), $redis->zrevrange('letters', 0, -1)); + $this->assertSame(array('f', 'e', 'd'), $redis->zrevrange('letters', 0, -4)); + $this->assertSame(array('d'), $redis->zrevrange('letters', 2, -4)); + $this->assertSame(array('f', 'e', 'd', 'c', 'b', 'a'), $redis->zrevrange('letters', -100, 100)); + + $this->assertSame(array(), $redis->zrevrange('unknown', 0, 30)); + } + + /** + * @group connected + */ + public function testRangeWithWithscoresModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + $expected = array(array('d', '20'), array('c', '10'), array('b', '0')); + + $this->assertSame($expected, $redis->zrevrange('letters', 2, 4, 'withscores')); + $this->assertSame($expected, $redis->zrevrange('letters', 2, 4, array('withscores' => true))); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrevrange('foo', 0, 10); + } +} diff --git a/tests/Predis/Commands/ZSetReverseRankTest.php b/tests/Predis/Commands/ZSetReverseRankTest.php new file mode 100644 index 00000000..a2bbc88e --- /dev/null +++ b/tests/Predis/Commands/ZSetReverseRankTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetReverseRankTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetReverseRank'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZREVRANK'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'member'); + $expected = array('key', 'member'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'member'); + $expected = array('prefix:key', 'member'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsRank() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame(5, $redis->zrevrank('letters', 'a')); + $this->assertSame(4, $redis->zrevrank('letters', 'b')); + $this->assertSame(1, $redis->zrevrank('letters', 'e')); + + $this->assertNull($redis->zrevrank('unknown', 'a')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zrevrank('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/ZSetScoreTest.php b/tests/Predis/Commands/ZSetScoreTest.php new file mode 100644 index 00000000..aebaefd0 --- /dev/null +++ b/tests/Predis/Commands/ZSetScoreTest.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetScoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetScore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZSCORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $arguments = array('key', 'member'); + $expected = array('key', 'member'); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $arguments = array('key', 'member'); + $expected = array('prefix:key', 'member'); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testReturnsRank() + { + $redis = $this->getClient(); + + $redis->zadd('letters', -10, 'a', 0, 'b', 10, 'c', 20, 'd', 20, 'e', 30, 'f'); + + $this->assertSame('-10', $redis->zscore('letters', 'a')); + $this->assertSame('0', $redis->zscore('letters', 'b')); + $this->assertSame('20', $redis->zscore('letters', 'e')); + + $this->assertNull($redis->zscore('unknown', 'a')); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zscore('foo', 'bar'); + } +} diff --git a/tests/Predis/Commands/ZSetUnionStoreTest.php b/tests/Predis/Commands/ZSetUnionStoreTest.php new file mode 100644 index 00000000..d1bb599c --- /dev/null +++ b/tests/Predis/Commands/ZSetUnionStoreTest.php @@ -0,0 +1,210 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Commands; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @group commands + * @group realm-zset + */ +class ZSetUnionStoreTest extends CommandTestCase +{ + /** + * {@inheritdoc} + */ + protected function getExpectedCommand() + { + return 'Predis\Commands\ZSetUnionStore'; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedId() + { + return 'ZUNIONSTORE'; + } + + /** + * @group disconnected + */ + public function testFilterArguments() + { + $modifiers = array( + 'aggregate' => 'sum', + 'weights' => array(10, 100), + ); + $arguments = array('zset:destination', 2, 'zset1', 'zset2', $modifiers); + + $expected = array( + 'zset:destination', 2, 'zset1', 'zset2', 'WEIGHTS', 10, 100, 'AGGREGATE', 'sum' + ); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testFilterArgumentsSourceKeysAsSingleArray() + { + $modifiers = array( + 'aggregate' => 'sum', + 'weights' => array(10, 100), + ); + $arguments = array('zset:destination', array('zset1', 'zset2'), $modifiers); + + $expected = array( + 'zset:destination', 2, 'zset1', 'zset2', 'WEIGHTS', 10, 100, 'AGGREGATE', 'sum' + ); + + $command = $this->getCommand(); + $command->setArguments($arguments); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testParseResponse() + { + $this->assertSame(1, $this->getCommand()->parseResponse(1)); + } + + /** + * @group disconnected + */ + public function testPrefixKeys() + { + $modifiers = array( + 'aggregate' => 'sum', + 'weights' => array(10, 100), + ); + $arguments = array('zset:destination', 2, 'zset1', 'zset2', $modifiers); + + $expected = array( + 'prefix:zset:destination', 2, 'prefix:zset1', 'prefix:zset2', 'WEIGHTS', 10, 100, 'AGGREGATE', 'sum' + ); + + $command = $this->getCommandWithArgumentsArray($arguments); + $command->prefixKeys('prefix:'); + + $this->assertSame($expected, $command->getArguments()); + } + + /** + * @group connected + */ + public function testStoresUnionInNewSortedSet() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $this->assertSame(4, $redis->zunionstore('letters:out', 2, 'letters:1st', 'letters:2nd')); + $this->assertSame( + array(array('a', '1'), array('b', '3'), array('d', '3'), array('c', '5')), + $redis->zrange('letters:out', 0, -1, 'withscores') + ); + + $this->assertSame(3, $redis->zunionstore('letters:out', 2, 'letters:1st', 'letters:void')); + $this->assertSame(3, $redis->zunionstore('letters:out', 2, 'letters:void', 'letters:2nd')); + $this->assertSame(0, $redis->zunionstore('letters:out', 2, 'letters:void', 'letters:void')); + } + + /** + * @group connected + */ + public function testStoresUnionWithAggregateModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $options = array('aggregate' => 'min'); + $this->assertSame(4, $redis->zunionstore('letters:min', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame( + array(array('a', '1'), array('b', '1'), array('c', '2'), array('d', '3')), + $redis->zrange('letters:min', 0, -1, 'withscores') + ); + + $options = array('aggregate' => 'max'); + $this->assertSame(4, $redis->zunionstore('letters:max', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame( + array(array('a', '1'), array('b', '2'), array('c', '3'), array('d', '3')), + $redis->zrange('letters:max', 0, -1, 'withscores') + ); + + $options = array('aggregate' => 'sum'); + $this->assertSame(4, $redis->zunionstore('letters:sum', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame( + array(array('a', '1'), array('b', '3'), array('d', '3'), array('c', '5')), + $redis->zrange('letters:sum', 0, -1, 'withscores') + ); + } + + /** + * @group connected + */ + public function testStoresUnionWithWeightsModifier() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $options = array('weights' => array(2, 3)); + $this->assertSame(4, $redis->zunionstore('letters:out', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame( + array(array('a', '2'), array('b', '7'), array('d', '9'), array('c', '12')), + $redis->zrange('letters:out', 0, -1, 'withscores') + ); + } + + /** + * @group connected + */ + public function testStoresUnionWithCombinedModifiers() + { + $redis = $this->getClient(); + + $redis->zadd('letters:1st', 1, 'a', 2, 'b', 3, 'c'); + $redis->zadd('letters:2nd', 1, 'b', 2, 'c', 3, 'd'); + + $options = array('aggregate' => 'max', 'weights' => array(10, 15)); + $this->assertSame(4, $redis->zunionstore('letters:out', 2, 'letters:1st', 'letters:2nd', $options)); + $this->assertSame( + array(array('a', '10'), array('b', '20'), array('c', '30'), array('d', '45')), + $redis->zrange('letters:out', 0, -1, 'withscores') + ); + } + + /** + * @group connected + * @expectedException Predis\ServerException + * @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value + */ + public function testThrowsExceptionOnWrongType() + { + $redis = $this->getClient(); + + $redis->set('foo', 'bar'); + $redis->zunionstore('zset:destination', 1, 'foo'); + } +} diff --git a/tests/Predis/CommunicationExceptionTest.php b/tests/Predis/CommunicationExceptionTest.php new file mode 100644 index 00000000..9480e166 --- /dev/null +++ b/tests/Predis/CommunicationExceptionTest.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; +use Predis\Network\IConnectionSingle; + +/** + * + */ +class CommunicationExceptionTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testExceptionMessage() + { + $message = 'Connection error message.'; + $connection = $this->getMockedConnectionBase(); + $exception = $this->getException($connection, $message); + + $this->setExpectedException('Predis\CommunicationException', $message); + + throw $exception; + } + + /** + * @group disconnected + */ + public function testExceptionConnection() + { + $connection = $this->getMockedConnectionBase(); + $exception = $this->getException($connection, 'ERROR MESSAGE'); + + $this->assertSame($connection, $exception->getConnection()); + } + + /** + * @group disconnected + */ + public function testShouldResetConnection() + { + $connection = $this->getMockedConnectionBase(); + $exception = $this->getException($connection, 'ERROR MESSAGE'); + + $this->assertTrue($exception->shouldResetConnection()); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a mocked connection instance. + * + * @param mixed $parameters Connection parameters. + * @return IConnectionSingle + */ + protected function getMockedConnectionBase($parameters = null) + { + $builder = $this->getMockBuilder('Predis\Network\ConnectionBase'); + + if ($parameters === null) { + $builder->disableOriginalConstructor(); + } + else if (!$parameters instanceof IConnectionParameters) { + $parameters = new ConnectionParameters($parameters); + } + + return $builder->getMockForAbstractClass(array($parameters)); + } + + /** + * Returns a connection exception instance. + * + * @param IConnectionSingle $message Connection instance. + * @param string $message Exception message. + * @param int $code Exception code. + * @param \Exception $inner Inner exception. + * @return \Exception + */ + protected function getException(IConnectionSingle $connection, $message, $code = 0, \Exception $inner = null) + { + $arguments = array($connection, $message, $code, $inner); + $mock = $this->getMockForAbstractClass('Predis\CommunicationException', $arguments); + + return $mock; + } +} diff --git a/tests/Predis/ConnectionFactoryTest.php b/tests/Predis/ConnectionFactoryTest.php new file mode 100644 index 00000000..3832a2bd --- /dev/null +++ b/tests/Predis/ConnectionFactoryTest.php @@ -0,0 +1,353 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ConnectionFactoryTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testImplementsCorrectInterface() + { + $factory = new ConnectionFactory(); + + $this->assertInstanceOf('Predis\IConnectionFactory', $factory); + } + + /** + * @group disconnected + */ + public function testCreateConnection() + { + $factory = new ConnectionFactory(); + + $tcp = new ConnectionParameters(array( + 'scheme' => 'tcp', + 'host' => 'locahost', + )); + + $connection = $factory->create($tcp); + $parameters = $connection->getParameters(); + $this->assertInstanceOf('Predis\Network\StreamConnection', $connection); + $this->assertEquals($tcp->scheme, $parameters->scheme); + $this->assertEquals($tcp->host, $parameters->host); + $this->assertEquals($tcp->database, $parameters->database); + + + $unix = new ConnectionParameters(array( + 'scheme' => 'unix', + 'path' => '/tmp/redis.sock', + )); + + $connection = $factory->create($tcp); + $parameters = $connection->getParameters(); + $this->assertInstanceOf('Predis\Network\StreamConnection', $connection); + $this->assertEquals($tcp->scheme, $parameters->scheme); + $this->assertEquals($tcp->database, $parameters->database); + } + + /** + * @group disconnected + */ + public function testCreateConnectionWithNullParameters() + { + $factory = new ConnectionFactory(); + $connection = $factory->create(null); + $parameters = $connection->getParameters(); + + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + $this->assertEquals('tcp', $parameters->scheme); + $this->assertFalse($parameters->isSetByUser('custom')); + } + + /** + * @group disconnected + */ + public function testCreateConnectionWithArrayParameters() + { + $factory = new ConnectionFactory(); + $connection = $factory->create(array('scheme' => 'tcp', 'custom' => 'foobar')); + $parameters = $connection->getParameters(); + + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + $this->assertEquals('tcp', $parameters->scheme); + $this->assertTrue($parameters->isSetByUser('custom')); + } + + /** + * @group disconnected + */ + public function testCreateConnectionWithStringURI() + { + $factory = new ConnectionFactory(); + $connection = $factory->create('tcp://127.0.0.1?custom=foobar'); + $parameters = $connection->getParameters(); + + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + $this->assertEquals('tcp', $parameters->scheme); + $this->assertTrue($parameters->isSetByUser('custom')); + } + + /** + * @group disconnected + */ + public function testCreateConnectionWithoutInitializationCommands() + { + $profile = $this->getMock('Predis\Profiles\IServerProfile'); + $profile->expects($this->never())->method('create'); + + $factory = new ConnectionFactory(); + $parameters = new ConnectionParameters(); + $connection = $factory->create($parameters, $profile); + + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + } + + /** + * @group disconnected + */ + public function testCreateConnectionWithInitializationCommands() + { + $test = $this; + $database = 15; + $password = 'foobar'; + $commands = array(); + + $createCommand = function($id, $arguments) use($test, &$commands) { + $commands[$id] = $arguments; + return $test->getMock('Predis\Commands\ICommand'); + }; + + $profile = $this->getMock('Predis\Profiles\IServerProfile'); + $profile->expects($this->exactly(2)) + ->method('createCommand') + ->with($this->isType('string'), $this->isType('array')) + ->will($this->returnCallback($createCommand)); + + $factory = new ConnectionFactory(); + $parameters = new ConnectionParameters(array('database' => $database, 'password' => $password)); + $connection = $factory->create($parameters, $profile); + + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + $this->assertEquals(2, count($commands)); // TODO: assertCount()? + $this->assertEquals(array($database), $commands['select']); + $this->assertEquals(array($password), $commands['auth']); + } + + /** + * @group disconnected + */ + public function testCreateUndefinedConnection() + { + $scheme = 'unknown'; + $this->setExpectedException('InvalidArgumentException', "Unknown connection scheme: $scheme"); + + $factory = new ConnectionFactory(); + $factory->create(new ConnectionParameters(array('scheme' => $scheme))); + } + + /** + * @group disconnected + */ + public function testDefineConnectionWithFQN() + { + list(, $connectionClass) = $this->getMockConnectionClass(); + + $parameters = new ConnectionParameters(array('scheme' => 'foobar')); + $factory = new ConnectionFactory(); + + $factory->define($parameters->scheme, $connectionClass); + $connection = $factory->create($parameters); + + $this->assertInstanceOf($connectionClass, $connection); + } + + /** + * @group disconnected + */ + public function testDefineConnectionWithCallable() + { + list(, $connectionClass) = $this->getMockConnectionClass(); + + $parameters = new ConnectionParameters(array('scheme' => 'foobar')); + + $initializer = function($parameters) use($connectionClass) { + return new $connectionClass($parameters); + }; + + $initializerMock = $this->getMock('stdClass', array('__invoke')); + $initializerMock->expects($this->exactly(2)) + ->method('__invoke') + ->with($parameters) + ->will($this->returnCallback($initializer)); + + $factory = new ConnectionFactory(); + $factory->define($parameters->scheme, $initializerMock); + $connection1 = $factory->create($parameters); + $connection2 = $factory->create($parameters); + + $this->assertInstanceOf($connectionClass, $connection1); + $this->assertInstanceOf($connectionClass, $connection2); + $this->assertNotSame($connection1, $connection2); + } + + /** + * @group disconnected + */ + public function testDefineConnectionWithInvalidArgument() + { + $this->setExpectedException('InvalidArgumentException'); + + $factory = new ConnectionFactory(); + $factory->define('foobar', new \stdClass()); + } + + /** + * @group disconnected + */ + public function testUndefineDefinedConnection() + { + $this->setExpectedException('InvalidArgumentException', 'Unknown connection scheme: tcp'); + + $factory = new ConnectionFactory(); + $factory->undefine('tcp'); + $factory->create('tcp://127.0.0.1'); + } + + /** + * @group disconnected + */ + public function testUndefineUndefinedConnection() + { + $factory = new ConnectionFactory(); + $factory->undefine('unknown'); + $connection = $factory->create('tcp://127.0.0.1'); + + $this->assertInstanceOf('Predis\Network\IConnectionSingle', $connection); + } + + /** + * @group disconnected + */ + public function testDefineAndUndefineConnection() + { + list(, $connectionClass) = $this->getMockConnectionClass(); + + $factory = new ConnectionFactory(); + + $factory->define('redis', $connectionClass); + $this->assertInstanceOf($connectionClass, $factory->create('redis://127.0.0.1')); + + $factory->undefine('redis'); + $this->setExpectedException('InvalidArgumentException', 'Unknown connection scheme: redis'); + $factory->create('redis://127.0.0.1'); + } + + /** + * @group disconnected + */ + public function testClusterSkipCreationOnConnectionInstance() + { + list(, $connectionClass) = $this->getMockConnectionClass(); + + $cluster = $this->getMock('Predis\Network\IConnectionCluster'); + $cluster->expects($this->exactly(2)) + ->method('add') + ->with($this->isInstanceOf('Predis\Network\IConnectionSingle')); + + $factory = $this->getMock('Predis\ConnectionFactory', array('create')); + $factory->expects($this->never()) + ->method('create'); + + $factory->createCluster($cluster, array(new $connectionClass(), new $connectionClass())); + } + + /** + * @group disconnected + */ + public function testClusterWithMixedConnectionParameters() + { + list(, $connectionClass) = $this->getMockConnectionClass(); + + $cluster = $this->getMock('Predis\Network\IConnectionCluster'); + $cluster->expects($this->exactly(4)) + ->method('add') + ->with($this->isInstanceOf('Predis\Network\IConnectionSingle')); + + $factory = $this->getMock('Predis\ConnectionFactory', array('create')); + $factory->expects($this->exactly(3)) + ->method('create') + ->will($this->returnCallback(function($_, $_) use($connectionClass) { + return new $connectionClass; + })); + + $factory->createCluster($cluster, array(null, 'tcp://127.0.0.1', array('scheme' => 'tcp'), new $connectionClass())); + } + + /** + * @group disconnected + */ + public function testClusterWithEmptyListOfParameters() + { + $cluster = $this->getMock('Predis\Network\IConnectionCluster'); + $cluster->expects($this->never())->method('add'); + + $factory = $this->getMock('Predis\ConnectionFactory', array('create')); + $factory->expects($this->never())->method('create'); + + $factory->createCluster($cluster, array()); + } + + /** + * @group disconnected + * @todo We might want to add a test for IConnectionSingle::pushInitCommand(). + */ + public function testClusterWithServerProfileArgument() + { + list(, $connectionClass) = $this->getMockConnectionClass(); + + $cluster = $this->getMock('Predis\Network\IConnectionCluster'); + $profile = $this->getMock('Predis\Profiles\IServerProfile'); + + $factory = $this->getMock('Predis\ConnectionFactory', array('create')); + $factory->expects($this->exactly(2)) + ->method('create') + ->with($this->anything(), $profile) + ->will($this->returnCallback(function($_, $_) use($connectionClass) { + return new $connectionClass(); + })); + + $nodes = array('tcp://127.0.0.1:7001?password=foo', 'tcp://127.0.0.1:7002?password=bar'); + $factory->createCluster($cluster, $nodes, $profile); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a mocked Predis\Network\IConnectionSingle. + * + * @return Array Mock instance and class name + */ + protected function getMockConnectionClass() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + return array($connection, get_class($connection)); + } +} diff --git a/tests/Predis/ConnectionParametersTest.php b/tests/Predis/ConnectionParametersTest.php new file mode 100644 index 00000000..ea7d4d77 --- /dev/null +++ b/tests/Predis/ConnectionParametersTest.php @@ -0,0 +1,225 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @todo ConnectionParameters::define(); + * @todo ConnectionParameters::undefine(); + */ +class ConnectionParametersTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testDefaultValues() + { + $defaults = $this->getDefaultParametersArray(); + $parameters = new ConnectionParameters(); + + $this->assertEquals($defaults['scheme'], $parameters->scheme); + $this->assertEquals($defaults['host'], $parameters->host); + $this->assertEquals($defaults['port'], $parameters->port); + $this->assertEquals($defaults['throw_errors'], $parameters->throw_errors); + $this->assertEquals($defaults['iterable_multibulk'], $parameters->iterable_multibulk); + $this->assertEquals($defaults['connection_async'], $parameters->connection_async); + $this->assertEquals($defaults['connection_persistent'], $parameters->connection_persistent); + $this->assertEquals($defaults['connection_timeout'], $parameters->connection_timeout); + $this->assertEquals($defaults['read_write_timeout'], $parameters->read_write_timeout); + $this->assertEquals($defaults['database'], $parameters->database); + $this->assertEquals($defaults['password'], $parameters->password); + $this->assertEquals($defaults['alias'], $parameters->alias); + $this->assertEquals($defaults['weight'], $parameters->weight); + $this->assertEquals($defaults['path'], $parameters->path); + } + + /** + * @group disconnected + */ + public function testIsSet() + { + $parameters = new ConnectionParameters(); + + $this->assertTrue(isset($parameters->scheme)); + $this->assertFalse(isset($parameters->unknown)); + } + + /** + * @group disconnected + */ + public function testIsSetByUser() + { + $parameters = new ConnectionParameters(array('port' => 7000, 'custom' => 'foobar')); + + $this->assertTrue(isset($parameters->scheme)); + $this->assertFalse($parameters->isSetByUser('scheme')); + + $this->assertTrue(isset($parameters->port)); + $this->assertTrue($parameters->isSetByUser('port')); + + $this->assertTrue(isset($parameters->custom)); + $this->assertTrue($parameters->isSetByUser('custom')); + + $this->assertFalse(isset($parameters->unknown)); + $this->assertFalse($parameters->isSetByUser('unknown')); + } + + /** + * @group disconnected + */ + public function testConstructWithUriString() + { + $defaults = $this->getDefaultParametersArray(); + + $overrides = array( + 'port' => 7000, + 'database' => 5, + 'throw_errors' => false, + 'custom' => 'foobar', + ); + + $parameters = new ConnectionParameters($this->getParametersString($overrides)); + + $this->assertEquals($defaults['scheme'], $parameters->scheme); + $this->assertEquals($defaults['host'], $parameters->host); + $this->assertEquals($overrides['port'], $parameters->port); + + $this->assertEquals($overrides['database'], $parameters->database); + $this->assertEquals($overrides['throw_errors'], $parameters->throw_errors); + + $this->assertTrue(isset($parameters->custom)); + $this->assertTrue($parameters->isSetByUser('custom')); + $this->assertEquals($overrides['custom'], $parameters->custom); + + $this->assertFalse(isset($parameters->unknown)); + $this->assertFalse($parameters->isSetByUser('unknown')); + } + + /** + * @group disconnected + */ + public function testToArray() + { + $additional = array('port' => 7000, 'custom' => 'foobar'); + $parameters = new ConnectionParameters($additional); + + $this->assertEquals($this->getParametersArray($additional), $parameters->toArray()); + } + + /** + * @group disconnected + */ + public function testToString() + { + $uri = 'tcp://localhost:7000/?database=15&custom=foobar&throw_errors=0'; + $parameters = new ConnectionParameters($uri); + + $this->assertEquals($uri, (string) $parameters); + } + + /** + * @group disconnected + * @todo Does it actually make sense? + */ + public function testToStringOmitPassword() + { + $uri = 'tcp://localhost:7000/?database=15&custom=foobar&throw_errors=0'; + $parameters = new ConnectionParameters($uri . '&password=foobar'); + + $this->assertEquals($uri, (string) $parameters); + } + + /** + * @group disconnected + */ + public function testSerialization() + { + $parameters = new ConnectionParameters(array('port' => 7000, 'custom' => 'foobar')); + $unserialized = unserialize(serialize($parameters)); + + $this->assertEquals($parameters->scheme, $unserialized->scheme); + $this->assertEquals($parameters->port, $unserialized->port); + + $this->assertTrue(isset($unserialized->custom)); + $this->assertTrue($unserialized->isSetByUser('custom')); + $this->assertEquals($parameters->custom, $unserialized->custom); + + $this->assertFalse(isset($unserialized->unknown)); + $this->assertFalse($unserialized->isSetByUser('unknown')); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a named array with the default connection parameters and their values. + * + * @return Array Default connection parameters. + */ + protected function getDefaultParametersArray() + { + return array( + 'scheme' => 'tcp', + 'host' => '127.0.0.1', + 'port' => 6379, + 'database' => null, + 'password' => null, + 'connection_async' => false, + 'connection_persistent' => false, + 'connection_timeout' => 5.0, + 'read_write_timeout' => null, + 'alias' => null, + 'weight' => null, + 'path' => null, + 'iterable_multibulk' => false, + 'throw_errors' => true, + ); + } + + /** + * Returns a named array with the default connection parameters merged with + * the specified additional parameters. + * + * @param Array $additional Additional connection parameters. + * @return Array Connection parameters. + */ + protected function getParametersArray(Array $additional) + { + return array_merge($this->getDefaultParametersArray(), $additional); + } + + /** + * Returns an URI string representation of the specified connection parameters. + * + * @param Array $parameters Array of connection parameters. + * @return String URI string. + */ + protected function getParametersString(Array $parameters) + { + $defaults = $this->getDefaultParametersArray(); + + $scheme = isset($parameters['scheme']) ? $parameters['scheme'] : $defaults['scheme']; + $host = isset($parameters['host']) ? $parameters['host'] : $defaults['host']; + $port = isset($parameters['port']) ? $parameters['port'] : $defaults['port']; + + unset($parameters['scheme'], $parameters['host'], $parameters['port']); + $uriString = "$scheme://$host:$port/?"; + + foreach ($parameters as $k => $v) { + $uriString .= "$k=$v&"; + } + + return $uriString; + } +} diff --git a/tests/Predis/Distribution/EmptyRingExceptionTest.php b/tests/Predis/Distribution/EmptyRingExceptionTest.php new file mode 100644 index 00000000..a17a9039 --- /dev/null +++ b/tests/Predis/Distribution/EmptyRingExceptionTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Distribution; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * @todo Not really useful right now. + */ +class EmptyRingExceptionTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testExceptionMessage() + { + $message = 'Empty Ring'; + $this->setExpectedException('Predis\Distribution\EmptyRingException', $message); + + throw new EmptyRingException($message); + } +} diff --git a/tests/Predis/Distribution/HashRingTest.php b/tests/Predis/Distribution/HashRingTest.php new file mode 100644 index 00000000..0bda99b0 --- /dev/null +++ b/tests/Predis/Distribution/HashRingTest.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Distribution; + +/** + * @todo To be improved. + */ +class HashRingTest extends DistributionStrategyTestCase +{ + /** + * {@inheritdoc} + */ + public function getDistributorInstance() + { + return new HashRing(); + } + + /** + * @group disconnected + */ + public function testGenerateKey() + { + $ring = $this->getDistributorInstance(); + + $this->assertEquals(crc32('foobar'), $ring->generateKey('foobar')); + } + + /** + * @group disconnected + */ + public function testSingleNodeInRing() + { + $node = '127.0.0.1:7000'; + + $ring = $this->getDistributorInstance(); + $ring->add($node); + + $expected = array_fill(0, 20, $node); + $actual = $this->getNodes($ring, 20); + + $this->assertSame($expected, $actual); + } + + /** + * @group disconnected + */ + public function testMultipleNodesInRing() + { + $nodes = array( + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7002', + ); + + $ring = $this->getDistributorInstance(); + foreach ($nodes as $node) { + $ring->add($node); + } + + $expected = array( + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7002', + '127.0.0.1:7002', + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7002', + '127.0.0.1:7002', + '127.0.0.1:7002', + '127.0.0.1:7002', + '127.0.0.1:7000', + '127.0.0.1:7002', + '127.0.0.1:7002', + '127.0.0.1:7002', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7002', + ); + + $actual = $this->getNodes($ring, 20); + + $this->assertSame($expected, $actual); + } + + /** + * @group disconnected + */ + public function testSubsequendAddAndRemoveFromRing() + { + $ring = $this->getDistributorInstance(); + + $expected1 = array_fill(0, 10, '127.0.0.1:7000'); + $expected3 = array_fill(0, 10, '127.0.0.1:7001'); + $expected2 = array( + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + ); + + $ring->add('127.0.0.1:7000'); + $actual1 = $this->getNodes($ring, 10); + + $ring->add('127.0.0.1:7001'); + $actual2 = $this->getNodes($ring, 10); + + $ring->remove('127.0.0.1:7000'); + $actual3 = $this->getNodes($ring, 10); + + $this->assertSame($expected1, $actual1); + $this->assertSame($expected2, $actual2); + $this->assertSame($expected3, $actual3); + } +} diff --git a/tests/Predis/Distribution/KetamaPureRingTest.php b/tests/Predis/Distribution/KetamaPureRingTest.php new file mode 100644 index 00000000..8552a1b1 --- /dev/null +++ b/tests/Predis/Distribution/KetamaPureRingTest.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Distribution; + +/** + * @todo To be improved. + */ +class KetamaPureRingTest extends DistributionStrategyTestCase +{ + /** + * {@inheritdoc} + */ + public function getDistributorInstance() + { + return new KetamaPureRing(); + } + + /** + * @group disconnected + */ + public function testGenerateKey() + { + $ring = $this->getDistributorInstance(); + list(, $hash) = unpack('V', md5('foobar', true)); + + $this->assertEquals($hash, $ring->generateKey('foobar')); + } + + /** + * @group disconnected + */ + public function testSingleNodeInRing() + { + $node = '127.0.0.1:7000'; + + $ring = $this->getDistributorInstance(); + $ring->add($node); + + $expected = array_fill(0, 20, $node); + $actual = $this->getNodes($ring, 20); + + $this->assertSame($expected, $actual); + } + + /** + * @group disconnected + */ + public function testMultipleNodesInRing() + { + $nodes = array( + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7002', + ); + + $ring = $this->getDistributorInstance(); + foreach ($nodes as $node) { + $ring->add($node); + } + + $expected = array( + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7002', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7002', + '127.0.0.1:7000', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7002', + '127.0.0.1:7000', + '127.0.0.1:7002', + '127.0.0.1:7001', + '127.0.0.1:7002', + ); + + $actual = $this->getNodes($ring, 20); + + $this->assertSame($expected, $actual); + } + + /** + * @group disconnected + */ + public function testSubsequendAddAndRemoveFromRing() + { + $ring = $this->getDistributorInstance(); + + $expected1 = array_fill(0, 10, '127.0.0.1:7000'); + $expected3 = array_fill(0, 10, '127.0.0.1:7001'); + $expected2 = array( + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + '127.0.0.1:7000', + '127.0.0.1:7001', + ); + + $ring->add('127.0.0.1:7000'); + $actual1 = $this->getNodes($ring, 10); + + $ring->add('127.0.0.1:7001'); + $actual2 = $this->getNodes($ring, 10); + + $ring->remove('127.0.0.1:7000'); + $actual3 = $this->getNodes($ring, 10); + + $this->assertSame($expected1, $actual1); + $this->assertSame($expected2, $actual2); + $this->assertSame($expected3, $actual3); + } +} diff --git a/tests/Predis/HelpersTest.php b/tests/Predis/HelpersTest.php new file mode 100644 index 00000000..213f7646 --- /dev/null +++ b/tests/Predis/HelpersTest.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class HelpersTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testConnectionIsCluster() + { + $single = $this->getMock('Predis\Network\IConnectionSingle'); + $cluster = $this->getMock('Predis\Network\IConnectionCluster'); + + $this->assertFalse(Helpers::isCluster($single)); + $this->assertTrue(Helpers::isCluster($cluster)); + } + + /** + * @group disconnected + */ + public function testOnCommunicationException() + { + $this->setExpectedException('Predis\CommunicationException'); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once())->method('isConnected')->will($this->returnValue(true)); + $connection->expects($this->once())->method('disconnect'); + + $exception = $this->getMockForAbstractClass('Predis\CommunicationException', array($connection)); + + Helpers::onCommunicationException($exception); + } + + /** + * @group disconnected + */ + public function testFilterArrayArguments() + { + $arguments = array('arg1', 'arg2', 'arg3', 'arg4'); + + $this->assertSame($arguments, Helpers::filterArrayArguments($arguments)); + $this->assertSame($arguments, Helpers::filterArrayArguments(array($arguments))); + + $arguments = array(array(), array()); + $this->assertSame($arguments, Helpers::filterArrayArguments($arguments)); + + $arguments = array(new \stdClass()); + $this->assertSame($arguments, Helpers::filterArrayArguments($arguments)); + } + + /** + * @group disconnected + */ + public function testFilterVariadicValues() + { + $arguments = array('key', 'value1', 'value2', 'value3'); + + $this->assertSame($arguments, Helpers::filterVariadicValues($arguments)); + $this->assertSame($arguments, Helpers::filterVariadicValues(array('key', array('value1', 'value2', 'value3')))); + + $arguments = array(array(), array()); + $this->assertSame($arguments, Helpers::filterArrayArguments($arguments)); + + $arguments = array(new \stdClass()); + $this->assertSame($arguments, Helpers::filterArrayArguments($arguments)); + } + + /** + * @group disconnected + */ + public function testExtractKeyTag() + { + $this->assertEquals('foo:bar', Helpers::extractKeyTag('foo:bar')); + $this->assertEquals('foo:', Helpers::extractKeyTag('{foo:}bar')); + $this->assertEquals('bar', Helpers::extractKeyTag('foo:{bar}')); + $this->assertEquals('foo:bar', Helpers::extractKeyTag('{foo:bar}')); + $this->assertEquals('', Helpers::extractKeyTag('foo{}:bar')); + $this->assertEquals('', Helpers::extractKeyTag('')); + $this->assertEquals('', Helpers::extractKeyTag('{}')); + } +} diff --git a/tests/Predis/Iterators/MultiBulkResponseSimpleTest.php b/tests/Predis/Iterators/MultiBulkResponseSimpleTest.php new file mode 100644 index 00000000..ac9de50d --- /dev/null +++ b/tests/Predis/Iterators/MultiBulkResponseSimpleTest.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Iterators; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; + +/** + * @group realm-iterators + */ +class MultiBulkResponseSimpleTest extends StandardTestCase +{ + /** + * @group connected + */ + public function testIterableMultibulk() + { + $client = $this->getClient(); + $client->rpush('metavars', 'foo', 'hoge', 'lol'); + + $this->assertInstanceOf('Iterator', $iterator = $client->lrange('metavars', 0, -1)); + $this->assertInstanceOf('Predis\Iterators\MultiBulkResponseSimple', $iterator); + $this->assertTrue($iterator->valid()); + $this->assertSame(3, $iterator->count()); + + $this->assertSame('foo', $iterator->current()); + $this->assertSame(1, $iterator->next()); + $this->assertTrue($iterator->valid()); + + $this->assertSame('hoge', $iterator->current()); + $this->assertSame(2, $iterator->next()); + $this->assertTrue($iterator->valid()); + + $this->assertSame('lol', $iterator->current()); + $this->assertSame(3, $iterator->next()); + $this->assertFalse($iterator->valid()); + + $this->assertTrue($client->ping()); + } + + /** + * @group connected + */ + public function testSyncWithFalseConsumesReplyFromUnderlyingConnection() + { + $client = $this->getClient(); + $client->rpush('metavars', 'foo', 'hoge', 'lol'); + + $iterator = $client->lrange('metavars', 0, -1); + $iterator->sync(false); + + $this->assertTrue($client->isConnected()); + $this->assertTrue($client->ping()); + } + + /** + * @group connected + */ + public function testSyncWithTrueDropsUnderlyingConnection() + { + $client = $this->getClient(); + $client->rpush('metavars', 'foo', 'hoge', 'lol'); + + $iterator = $client->lrange('metavars', 0, -1); + $iterator->sync(true); + + $this->assertFalse($client->isConnected()); + $this->assertTrue($client->ping()); + } + + /** + * @group connected + */ + public function testGarbageCollectorDropsUnderlyingConnection() + { + $client = $this->getClient(); + $client->rpush('metavars', 'foo', 'hoge', 'lol'); + + $iterator = $client->lrange('metavars', 0, -1); + + unset($iterator); + + $this->assertFalse($client->isConnected()); + $this->assertTrue($client->ping()); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a new client instance. + * + * @return Client + */ + protected function getClient() + { + $parameters = array( + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'iterable_multibulk' => true, + 'read_write_timeout' => 2, + ); + + $client = new Client($parameters, REDIS_SERVER_VERSION); + $client->connect(); + $client->select(REDIS_SERVER_DBNUM); + $client->flushdb(); + + return $client; + } + +} diff --git a/tests/Predis/Iterators/MultiBulkResponseTupleTest.php b/tests/Predis/Iterators/MultiBulkResponseTupleTest.php new file mode 100644 index 00000000..7c01518b --- /dev/null +++ b/tests/Predis/Iterators/MultiBulkResponseTupleTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Iterators; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; + +/** + * @group realm-iterators + */ +class MultiBulkResponseTupleTest extends StandardTestCase +{ + /** + * @group connected + */ + public function testIterableMultibulk() + { + $client = $this->getClient(); + $client->zadd('metavars', 1, 'foo', 2, 'hoge', 3, 'lol'); + + $this->assertInstanceOf('OuterIterator', $iterator = $client->zrange('metavars', 0, -1, 'withscores')); + $this->assertInstanceOf('Predis\Iterators\MultiBulkResponseTuple', $iterator); + $this->assertInstanceOf('Predis\Iterators\MultiBulkResponseSimple', $iterator->getInnerIterator()); + $this->assertTrue($iterator->valid()); + $this->assertSame(3, $iterator->count()); + + $this->assertSame(array('foo', '1'), $iterator->current()); + $this->assertSame(1, $iterator->next()); + $this->assertTrue($iterator->valid()); + + $this->assertSame(array('hoge', '2'), $iterator->current()); + $this->assertSame(2, $iterator->next()); + $this->assertTrue($iterator->valid()); + + $this->assertSame(array('lol', '3'), $iterator->current()); + $this->assertSame(3, $iterator->next()); + $this->assertFalse($iterator->valid()); + + $this->assertTrue($client->ping()); + } + + /** + * @group connected + */ + public function testGarbageCollectorDropsUnderlyingConnection() + { + $client = $this->getClient(); + $client->zadd('metavars', 1, 'foo', 2, 'hoge', 3, 'lol'); + + $iterator = $client->zrange('metavars', 0, -1, 'withscores'); + + unset($iterator); + + $this->assertFalse($client->isConnected()); + $this->assertTrue($client->ping()); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a new client instance. + * + * @return Client + */ + protected function getClient() + { + $parameters = array( + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'iterable_multibulk' => true, + 'read_write_timeout' => 2, + ); + + $client = new Client($parameters, REDIS_SERVER_VERSION); + $client->connect(); + $client->select(REDIS_SERVER_DBNUM); + $client->flushdb(); + + return $client; + } + +} diff --git a/tests/Predis/MonitorContextTest.php b/tests/Predis/MonitorContextTest.php new file mode 100644 index 00000000..2e72c577 --- /dev/null +++ b/tests/Predis/MonitorContextTest.php @@ -0,0 +1,171 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Profiles\ServerProfile; + +/** + * @group realm-monitor + */ +class MonitorContextTest extends StandardTestCase +{ + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The current profile does not support the MONITOR command + */ + public function testMonitorContextRequireMonitorCommand() + { + $profile = $this->getMock('Predis\Profiles\IServerProfile'); + $profile->expects($this->once()) + ->method('supportsCommand') + ->with('monitor') + ->will($this->returnValue(false)); + + $client = new Client(null, array('profile' => $profile)); + $monitor = new MonitorContext($client); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage Cannot initialize a monitor context over a cluster of connections + */ + public function testMonitorContextDoesNotWorkOnClusters() + { + $cluster = $this->getMock('Predis\Network\IConnectionCluster'); + + $client = new Client($cluster); + $monitor = new MonitorContext($client); + } + + /** + * @group disconnected + */ + public function testConstructorOpensContext() + { + $cmdMonitor = ServerProfile::getDefault()->createCommand('monitor'); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + $client = $this->getMock('Predis\Client', array('createCommand', 'executeCommand'), array($connection)); + $client->expects($this->once()) + ->method('createCommand') + ->with('monitor', array()) + ->will($this->returnValue($cmdMonitor)); + $client->expects($this->once()) + ->method('executeCommand') + ->with($cmdMonitor); + + $monitor = new MonitorContext($client); + } + + /** + * @group disconnected + * @todo We should investigate why disconnect is invoked 2 times in this test, + * but the reason is probably that the GC invokes __destruct() on monitor + * thus calling $client->disconnect() a second time at the end of the test. + */ + public function testClosingContextClosesConnection() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + $client = $this->getMock('Predis\Client', array('disconnect'), array($connection)); + $client->expects($this->exactly(2))->method('disconnect'); + + $monitor = new MonitorContext($client); + $monitor->closeContext(); + } + + /** + * @group disconnected + */ + public function testGarbageCollectorRunClosesContext() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + $client = $this->getMock('Predis\Client', array('disconnect'), array($connection)); + $client->expects($this->once())->method('disconnect'); + + $monitor = new MonitorContext($client); + unset($monitor); + } + + /** + * @group disconnected + */ + public function testCurrentReadsMessageFromConnection() + { + $message = '1323367530.939137 (db 15) "MONITOR"'; + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once()) + ->method('read') + ->will($this->returnValue($message)); + + $client = new Client($connection); + $monitor = new MonitorContext($client); + + $payload = $monitor->current(); + $this->assertSame(1323367530, (int) $payload->timestamp); + $this->assertSame(15, $payload->database); + $this->assertSame('MONITOR', $payload->command); + $this->assertNull($payload->arguments); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testMonitorAgainstRedisServer() + { + $parameters = array( + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'database' => REDIS_SERVER_DBNUM, + // Prevents suite from handing on broken test + 'read_write_timeout' => 2, + ); + + $echoed = array(); + + $producer = new Client($parameters, REDIS_SERVER_VERSION); + $producer->connect(); + + $consumer = new Client($parameters, REDIS_SERVER_VERSION); + $consumer->connect(); + + $monitor = new MonitorContext($consumer); + + $producer->echo('message1'); + $producer->echo('message2'); + $producer->echo('QUIT'); + + foreach ($monitor as $message) { + if ($message->command == 'ECHO') { + $echoed[] = $arguments = trim($message->arguments, '"'); + if ($arguments == 'QUIT') { + $monitor->closeContext(); + } + } + } + + $this->assertSame(array('message1', 'message2', 'QUIT'), $echoed); + $this->assertFalse($monitor->valid()); + $this->assertTrue($consumer->ping()); + } +} diff --git a/tests/Predis/Network/ConnectionExceptionTest.php b/tests/Predis/Network/ConnectionExceptionTest.php new file mode 100644 index 00000000..18ae3e06 --- /dev/null +++ b/tests/Predis/Network/ConnectionExceptionTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Network; + +require_once __DIR__.'/../CommunicationExceptionTest.php'; + +use Predis\CommunicationExceptionTest; +use Predis\Network\IConnectionSingle; + +/** + * + */ +class ConnectionExceptionTest extends CommunicationExceptionTest +{ + /** + * {@inheritdoc} + */ + protected function getException(IConnectionSingle $connection, $message, $code = 0, \Exception $inner = null) + { + return new ConnectionException($connection, $message, $code, $inner); + } +} diff --git a/tests/Predis/Network/PhpiredisConnectionTest.php b/tests/Predis/Network/PhpiredisConnectionTest.php new file mode 100644 index 00000000..4999a402 --- /dev/null +++ b/tests/Predis/Network/PhpiredisConnectionTest.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Network; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\ConnectionParameters; +use Predis\Profiles\ServerProfile; + +/** + * @group ext-phpiredis + */ +class PhpiredisConnectionTest extends ConnectionTestCase +{ + /** + * @group disconnected + */ + public function testConstructorDoesNotOpenConnection() + { + $connection = new PhpiredisConnection($this->getParameters()); + + $this->assertFalse($connection->isConnected()); + } + + /** + * @group disconnected + */ + public function testExposesConnectionParameters() + { + $parameters = $this->getParameters(); + $connection = new PhpiredisConnection($parameters); + + $this->assertSame($parameters, $connection->getParameters()); + } + + /** + * @group disconnected + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Invalid scheme: udp + */ + public function testThrowsExceptionOnInvalidScheme() + { + $parameters = $this->getParameters(array('scheme' => 'udp')); + $connection = new PhpiredisConnection($parameters); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testExecutesCommandsOnServer() + { + $connection = $this->getConnection($profile, true); + + $cmdPing = $profile->createCommand('ping'); + $cmdEcho = $profile->createCommand('echo', array('echoed')); + $cmdGet = $profile->createCommand('get', array('foobar')); + $cmdRpush = $profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')); + $cmdLrange = $profile->createCommand('lrange', array('metavars', 0, -1)); + + $this->assertTrue($connection->executeCommand($cmdPing)); + $this->assertSame('echoed', $connection->executeCommand($cmdEcho)); + $this->assertNull($connection->executeCommand($cmdGet)); + $this->assertSame(3, $connection->executeCommand($cmdRpush)); + $this->assertSame(array('foo', 'hoge', 'lol'), $connection->executeCommand($cmdLrange)); + } + + /** + * @group connected + * @expectedException Predis\Protocol\ProtocolException + * @expectedExceptionMessage Protocol error, got "P" as reply type byte + */ + public function testThrowsExceptionOnProtocolDesynchronizationErrors() + { + $connection = $this->getConnection($profile); + $socket = $connection->getResource(); + + $connection->writeCommand($profile->createCommand('ping')); + socket_read($socket, 1); + + $connection->read(); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * {@inheritdoc} + */ + protected function getConnection(&$profile = null, $initialize = false, Array $parameters = array()) + { + $parameters = $this->getParameters($parameters); + $profile = $this->getProfile(); + + $connection = new PhpiredisConnection($parameters); + + if ($initialize) { + $connection->pushInitCommand($profile->createCommand('select', array($parameters->database))); + $connection->pushInitCommand($profile->createCommand('flushdb')); + } + + return $connection; + } +} diff --git a/tests/Predis/Network/PredisClusterTest.php b/tests/Predis/Network/PredisClusterTest.php new file mode 100644 index 00000000..2fefa12b --- /dev/null +++ b/tests/Predis/Network/PredisClusterTest.php @@ -0,0 +1,311 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Network; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\ConnectionParameters; +use Predis\Profiles\ServerProfile; + +/** + * + */ +class PredisClusterTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testAddingConnectionsToCluster() + { + $connection1 = $this->getMockConnection(); + $connection2 = $this->getMockConnection(); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $this->assertSame($connection1, $cluster->getConnectionById(0)); + $this->assertSame($connection2, $cluster->getConnectionById(1)); + } + + /** + * @group disconnected + */ + public function testAddingConnectionsToClusterUsesConnectionAlias() + { + $connection1 = $this->getMockConnection('tcp://host1:7001?alias=node1'); + $connection2 = $this->getMockConnection('tcp://host1:7002?alias=node2'); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $this->assertSame($connection1, $cluster->getConnectionById('node1')); + $this->assertSame($connection2, $cluster->getConnectionById('node2')); + } + + /** + * @group disconnected + */ + public function testConnectForcesAllConnectionsToConnect() + { + $connection1 = $this->getMockConnection(); + $connection1->expects($this->once())->method('connect'); + + $connection2 = $this->getMockConnection(); + $connection2->expects($this->once())->method('connect'); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $cluster->connect(); + } + + /** + * @group disconnected + */ + public function testDisconnectForcesAllConnectionsToDisconnect() + { + $connection1 = $this->getMockConnection(); + $connection1->expects($this->once())->method('disconnect'); + + $connection2 = $this->getMockConnection(); + $connection2->expects($this->once())->method('disconnect'); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $cluster->disconnect(); + } + + /** + * @group disconnected + */ + public function testIsConnectedReturnsTrueIfAtLeastOneConnectionIsOpen() + { + $connection1 = $this->getMockConnection(); + $connection1->expects($this->once()) + ->method('isConnected') + ->will($this->returnValue(false)); + + $connection2 = $this->getMockConnection(); + $connection2->expects($this->once()) + ->method('isConnected') + ->will($this->returnValue(true)); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $this->assertTrue($cluster->isConnected()); + } + + /** + * @group disconnected + */ + public function testIsConnectedReturnsFalseIfAllConnectionsAreClosed() + { + $connection1 = $this->getMockConnection(); + $connection1->expects($this->once()) + ->method('isConnected') + ->will($this->returnValue(false)); + + $connection2 = $this->getMockConnection(); + $connection2->expects($this->once()) + ->method('isConnected') + ->will($this->returnValue(false)); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $this->assertFalse($cluster->isConnected()); + } + + /** + * @group disconnected + */ + public function testCanReturnAnIteratorForConnections() + { + $connection1 = $this->getMockConnection(); + $connection2 = $this->getMockConnection(); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $this->assertInstanceOf('Iterator', $iterator = $cluster->getIterator()); + $connections = iterator_to_array($iterator); + + $this->assertSame($connection1, $connections[0]); + $this->assertSame($connection2, $connections[1]); + } + + /** + * @group disconnected + */ + public function testReturnsCorrectConnectionUsingKey() + { + $connection1 = $this->getMockConnection('tcp://host1:7001'); + $connection2 = $this->getMockConnection('tcp://host1:7002'); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $this->assertSame($connection1, $cluster->getConnectionByKey('node01:5431')); + $this->assertSame($connection2, $cluster->getConnectionByKey('node02:3212')); + $this->assertSame($connection1, $cluster->getConnectionByKey('prefix:{node01:5431}')); + $this->assertSame($connection2, $cluster->getConnectionByKey('prefix:{node02:3212}')); + } + + /** + * @group disconnected + */ + public function testReturnsCorrectConnectionUsingCommandInstance() + { + $profile = ServerProfile::getDefault(); + + $connection1 = $this->getMockConnection('tcp://host1:7001'); + $connection2 = $this->getMockConnection('tcp://host1:7002'); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $set = $profile->createCommand('set', array('node01:5431', 'foobar')); + $get = $profile->createCommand('get', array('node01:5431')); + $this->assertSame($connection1, $cluster->getConnection($set)); + $this->assertSame($connection1, $cluster->getConnection($get)); + + $set = $profile->createCommand('set', array('prefix:{node01:5431}', 'foobar')); + $get = $profile->createCommand('get', array('prefix:{node01:5431}')); + $this->assertSame($connection1, $cluster->getConnection($set)); + $this->assertSame($connection1, $cluster->getConnection($get)); + + $set = $profile->createCommand('set', array('node02:3212', 'foobar')); + $get = $profile->createCommand('get', array('node02:3212')); + $this->assertSame($connection2, $cluster->getConnection($set)); + $this->assertSame($connection2, $cluster->getConnection($get)); + + $set = $profile->createCommand('set', array('prefix:{node02:3212}', 'foobar')); + $get = $profile->createCommand('get', array('prefix:{node02:3212}')); + $this->assertSame($connection2, $cluster->getConnection($set)); + $this->assertSame($connection2, $cluster->getConnection($get)); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage Cannot send 'PING' commands to a cluster of connections + */ + public function testThrowsExceptionOnNonShardableCommand() + { + $ping = ServerProfile::getDefault()->createCommand('ping'); + + $cluster = new PredisCluster(); + $cluster->add($this->getMockConnection()); + + $cluster->getConnection($ping); + } + + /** + * @group disconnected + */ + public function testWritesCommandToCorrectConnection() + { + $command = ServerProfile::getDefault()->createCommand('get', array('node01:5431')); + + $connection1 = $this->getMockConnection('tcp://host1:7001'); + $connection1->expects($this->once())->method('writeCommand')->with($command); + + $connection2 = $this->getMockConnection('tcp://host1:7002'); + $connection2->expects($this->never())->method('writeCommand'); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $cluster->writeCommand($command); + } + + /** + * @group disconnected + */ + public function testReadsCommandFromCorrectConnection() + { + $command = ServerProfile::getDefault()->createCommand('get', array('node02:3212')); + + $connection1 = $this->getMockConnection('tcp://host1:7001'); + $connection1->expects($this->never())->method('readResponse'); + + $connection2 = $this->getMockConnection('tcp://host1:7002'); + $connection2->expects($this->once())->method('readResponse')->with($command); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $cluster->readResponse($command); + } + + /** + * @group disconnected + */ + public function testExecutesCommandOnCorrectConnection() + { + $command = ServerProfile::getDefault()->createCommand('get', array('node01:5431')); + + $connection1 = $this->getMockConnection('tcp://host1:7001'); + $connection1->expects($this->once())->method('executeCommand')->with($command); + + $connection2 = $this->getMockConnection('tcp://host1:7002'); + $connection2->expects($this->never())->method('executeCommand'); + + $cluster = new PredisCluster(); + $cluster->add($connection1); + $cluster->add($connection2); + + $cluster->executeCommand($command); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a base mocked connection from Predis\Network\IConnectionSingle. + * + * @param mixed $parameters Optional parameters. + * @return mixed + */ + protected function getMockConnection($parameters = null) + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + if ($parameters) { + $parameters = new ConnectionParameters($parameters); + $hash = "{$parameters->host}:{$parameters->port}"; + + $connection->expects($this->any()) + ->method('getParameters') + ->will($this->returnValue($parameters)); + $connection->expects($this->any()) + ->method('__toString') + ->will($this->returnValue($hash)); + } + + return $connection; + } +} diff --git a/tests/Predis/Network/StreamConnectionTest.php b/tests/Predis/Network/StreamConnectionTest.php new file mode 100644 index 00000000..f0ca7975 --- /dev/null +++ b/tests/Predis/Network/StreamConnectionTest.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Network; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\ConnectionParameters; +use Predis\Profiles\ServerProfile; + +/** + * + */ +class StreamConnectionTest extends ConnectionTestCase +{ + /** + * @group disconnected + */ + public function testConstructorDoesNotOpenConnection() + { + $connection = new StreamConnection($this->getParameters()); + + $this->assertFalse($connection->isConnected()); + } + + /** + * @group disconnected + */ + public function testExposesConnectionParameters() + { + $parameters = $this->getParameters(); + $connection = new StreamConnection($parameters); + + $this->assertSame($parameters, $connection->getParameters()); + } + + /** + * @group disconnected + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Invalid scheme: udp + */ + public function testThrowsExceptionOnInvalidScheme() + { + $parameters = $this->getParameters(array('scheme' => 'udp')); + $connection = new StreamConnection($parameters); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testReadsMultibulkRepliesAsIterators() + { + $connection = $this->getConnection($profile, true, array('iterable_multibulk' => true)); + + $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol'))); + $connection->writeCommand($profile->createCommand('lrange', array('metavars', 0, -1))); + + $this->assertInstanceOf('Predis\Iterators\MultiBulkResponse', $iterator = $connection->read()); + $this->assertSame(array('foo', 'hoge', 'lol'), iterator_to_array($iterator)); + } + + /** + * @group connected + * @expectedException Predis\Protocol\ProtocolException + * @expectedExceptionMessage Unknown prefix: 'P' + */ + public function testThrowsExceptionOnProtocolDesynchronizationErrors() + { + $connection = $this->getConnection($profile); + $stream = $connection->getResource(); + + $connection->writeCommand($profile->createCommand('ping')); + fread($stream, 1); + + $connection->read(); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * {@inheritdoc} + */ + protected function getConnection(&$profile = null, $initialize = false, Array $parameters = array()) + { + $parameters = $this->getParameters($parameters); + $profile = $this->getProfile(); + + $connection = new StreamConnection($parameters); + + if ($initialize) { + $connection->pushInitCommand($profile->createCommand('select', array($parameters->database))); + $connection->pushInitCommand($profile->createCommand('flushdb')); + } + + return $connection; + } +} diff --git a/tests/Predis/Network/WebdisConnectionTest.php b/tests/Predis/Network/WebdisConnectionTest.php new file mode 100644 index 00000000..901eaf8a --- /dev/null +++ b/tests/Predis/Network/WebdisConnectionTest.php @@ -0,0 +1,198 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Network; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\ConnectionParameters; +use Predis\Profiles\ServerProfile; + +/** + * @group realm-network + * @group ext-curl + * @group ext-phpiredis + * @group realm-network-webdis + */ +class WebdisConnectionTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testIsConnectedAlwaysReturnsTrue() + { + $connection = new WebdisConnection($this->getParameters()); + + $this->assertTrue($connection->isConnected()); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The method Predis\Network\WebdisConnection::writeCommand() is not supported + */ + public function testWritingCommandsIsNotSupported() + { + $connection = new WebdisConnection($this->getParameters()); + $connection->writeCommand($this->getProfile()->createCommand('ping')); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The method Predis\Network\WebdisConnection::readResponse() is not supported + */ + public function testReadingResponsesIsNotSupported() + { + $connection = new WebdisConnection($this->getParameters()); + $connection->readResponse($this->getProfile()->createCommand('ping')); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The method Predis\Network\WebdisConnection::read() is not supported + */ + public function testReadingFromConnectionIsNotSupported() + { + $connection = new WebdisConnection($this->getParameters()); + $connection->read(); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The method Predis\Network\WebdisConnection::pushInitCommand() is not supported + */ + public function testPushingInitCommandsIsNotSupported() + { + $connection = new WebdisConnection($this->getParameters()); + $connection->pushInitCommand($this->getProfile()->createCommand('ping')); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage Disabled command: SELECT + */ + public function testRejectCommandSelect() + { + $connection = new WebdisConnection($this->getParameters()); + $connection->executeCommand($this->getProfile()->createCommand('select', array(0))); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage Disabled command: AUTH + */ + public function testRejectCommandAuth() + { + $connection = new WebdisConnection($this->getParameters()); + $connection->executeCommand($this->getProfile()->createCommand('auth', array('foobar'))); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testExecutesCommandsOnServer() + { + $connection = $this->getConnection($profile); + + $cmdPing = $profile->createCommand('ping'); + $cmdEcho = $profile->createCommand('echo', array('echoed')); + $cmdGet = $profile->createCommand('get', array('foobar')); + $cmdRpush = $profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')); + $cmdLrange = $profile->createCommand('lrange', array('metavars', 0, -1)); + + $this->assertTrue($connection->executeCommand($cmdPing)); + $this->assertSame('echoed', $connection->executeCommand($cmdEcho)); + $this->assertNull($connection->executeCommand($cmdGet)); + $this->assertSame(3, $connection->executeCommand($cmdRpush)); + $this->assertSame(array('foo', 'hoge', 'lol'), $connection->executeCommand($cmdLrange)); + } + + /** + * @group disconnected + * @group slow + * @expectedException Predis\Network\ConnectionException + */ + public function testThrowExceptionWhenUnableToConnect() + { + $parameters = $this->getParameters(array('host' => '169.254.10.10')); + $connection = new WebdisConnection($parameters); + $connection->executeCommand($this->getProfile()->createCommand('ping')); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a named array with the default connection parameters and their values. + * + * @return Array Default connection parameters. + */ + protected function getDefaultParametersArray() + { + return array( + 'scheme' => 'http', + 'host' => WEBDIS_SERVER_HOST, + 'port' => WEBDIS_SERVER_PORT, + ); + } + + /** + * Returns a new instance of connection parameters. + * + * @param array $additional Additional connection parameters. + * @return ConnectionParameters Default connection parameters. + */ + protected function getParameters($additional = array()) + { + $parameters = array_merge($this->getDefaultParametersArray(), $additional); + $parameters = new ConnectionParameters($parameters); + + return $parameters; + } + + /** + * Returns a new instance of server profile. + * + * @param array $additional Additional connection parameters. + * @return ServerProfile + */ + protected function getProfile($version = null) + { + return ServerProfile::get($version ?: REDIS_SERVER_VERSION); + } + + /** + * Returns a new instance of a connection instance. + * + * @param array $parameters Additional connection parameters. + * @return WebdisConnection + */ + protected function getConnection(&$profile = null, Array $parameters = array()) + { + $parameters = $this->getParameters($parameters); + $profile = $this->getProfile(); + + $connection = new WebdisConnection($parameters); + $connection->executeCommand($profile->createCommand('flushdb')); + + return $connection; + } +} diff --git a/tests/Predis/Options/ClientClusterTest.php b/tests/Predis/Options/ClientClusterTest.php new file mode 100644 index 00000000..2cfe88db --- /dev/null +++ b/tests/Predis/Options/ClientClusterTest.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Options; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ClientClusterTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testValidationAcceptsFQNStringAsInitializer() + { + $clusterClass = get_class($this->getMock('Predis\Network\IConnectionCluster')); + + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientCluster(); + + $cluster = $option->validate($options, $clusterClass); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $cluster); + } + + /** + * @group disconnected + */ + public function testValidationRecognizesCertainPredefinedShortNames() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientCluster(); + + $cluster = $option->validate($options, 'predis'); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $cluster); + } + + /** + * @group disconnected + */ + public function testValidationAcceptsCallableObjectAsInitializers() + { + $value = $this->getMock('Predis\Network\IConnectionCluster'); + + $initializer = $this->getMock('stdClass', array('__invoke')); + $initializer->expects($this->once()) + ->method('__invoke') + ->with($this->isInstanceOf('Predis\Options\IClientOptions')) + ->will($this->returnValue($value)); + + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientCluster(); + + $cluster = $option->validate($options, $initializer); + + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $cluster); + $this->assertSame($value, $cluster); + } + + /** + * @group disconnected + */ + public function testValidationThrowsExceptionOnInvalidClassTypes() + { + $this->setExpectedException('InvalidArgumentException'); + + $connectionClass = get_class($this->getMock('Predis\Network\IConnectionSingle')); + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientCluster(); + + $option->validate($options, $connectionClass); + } + + /** + * @group disconnected + */ + public function testValidationThrowsExceptionOnInvalidShortName() + { + $this->setExpectedException('InvalidArgumentException'); + + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientCluster(); + + $option->validate($options, 'unknown'); + } + + /** + * @group disconnected + */ + public function testValidationThrowsExceptionOnInvalidObjectReturnedByCallback() + { + $this->setExpectedException('InvalidArgumentException'); + + $value = function($options) { return new \stdClass(); }; + + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientCluster(); + + $option->validate($options, $value); + } + + /** + * @group disconnected + */ + public function testValidationThrowsExceptionOnInvalidArguments() + { + $this->setExpectedException('InvalidArgumentException'); + + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientCluster(); + + $option->validate($options, new \stdClass()); + } +} diff --git a/tests/Predis/Options/ClientConnectionFactoryTest.php b/tests/Predis/Options/ClientConnectionFactoryTest.php new file mode 100644 index 00000000..9f4d33ba --- /dev/null +++ b/tests/Predis/Options/ClientConnectionFactoryTest.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Options; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\ConnectionFactory; + +/** + * + */ +class ClientConnectionFactoryTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testValidationReturnsDefaultFactoryWithSchemeDefinitionsArray() + { + $connectionClass = get_class($this->getMock('Predis\Network\IConnectionSingle')); + $value = array('tcp' => $connectionClass, 'redis' => $connectionClass); + + $options = $this->getMock('Predis\Options\IClientOptions'); + + $default = $this->getMock('Predis\IConnectionFactory'); + $default->expects($this->exactly(2)) + ->method('define') + ->with($this->matchesRegularExpression('/^tcp|redis$/'), $connectionClass); + + $option = $this->getMock('Predis\Options\ClientConnectionFactory', array('getDefault')); + $option->expects($this->once()) + ->method('getDefault') + ->with($options) + ->will($this->returnValue($default)); + + $factory = $option->validate($options, $value); + + $this->assertInstanceOf('Predis\IConnectionFactory', $factory); + $this->assertSame($default, $factory); + } + + /** + * @group disconnected + */ + public function testValidationAcceptsFactoryInstancesAsValue() + { + $value = $this->getMock('Predis\IConnectionFactory'); + $options = $this->getMock('Predis\Options\IClientOptions'); + + $option = $this->getMock('Predis\Options\ClientConnectionFactory', array('getDefault')); + $option->expects($this->never())->method('getDefault'); + + $this->assertSame($value, $option->validate($options, $value)); + } + + /** + * @group disconnected + */ + public function testValidationAcceptsStringAsValue() + { + $factory = 'Predis\ConnectionFactory'; + $options = $this->getMock('Predis\Options\IClientOptions'); + + $option = $this->getMock('Predis\Options\ClientConnectionFactory', array('getDefault')); + $option->expects($this->never())->method('getDefault'); + + $this->assertInstanceOf($factory, $option->validate($options, $factory)); + } + + /** + * @group disconnected + */ + public function testValidationThrowsExceptionOnWrongInvalidArguments() + { + $this->setExpectedException('InvalidArgumentException'); + + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientConnectionFactory(); + + $option->validate($options, new \stdClass()); + } + + /** + * @group disconnected + */ + public function testInvokeReturnsSpecifiedFactoryOrDefault() + { + $value = $this->getMock('Predis\IConnectionFactory'); + $options = $this->getMock('Predis\Options\IClientOptions'); + + $option = $this->getMock('Predis\Options\ClientConnectionFactory', array('validate', 'getDefault')); + $option->expects($this->once()) + ->method('validate') + ->with($options, $value) + ->will($this->returnValue($value)); + $option->expects($this->never())->method('getDefault'); + + $this->assertInstanceOf('Predis\IConnectionFactory', $option($options, $value)); + + $option = $this->getMock('Predis\Options\ClientConnectionFactory', array('validate', 'getDefault')); + $option->expects($this->never())->method('validate'); + $option->expects($this->once()) + ->method('getDefault') + ->with($options) + ->will($this->returnValue($value)); + + $this->assertInstanceOf('Predis\IConnectionFactory', $option($options, null)); + } +} diff --git a/tests/Predis/Options/ClientOptionsTest.php b/tests/Predis/Options/ClientOptionsTest.php new file mode 100644 index 00000000..a2b1090a --- /dev/null +++ b/tests/Predis/Options/ClientOptionsTest.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Options; + +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\Profiles\IServerProfile', $options->profile); + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $options->cluster); + $this->assertInstanceOf('Predis\IConnectionFactory', $options->connections); + $this->assertNull($options->prefix); + } + + /** + * @group disconnected + */ + public function testConstructorWithArrayArgument() + { + $options = new ClientOptions(array( + 'cluster' => 'Predis\Network\PredisCluster', + 'connections' => 'Predis\ConnectionFactory', + 'prefix' => 'prefix:', + 'profile' => '2.0', + )); + + $this->assertInstanceOf('Predis\Commands\Processors\ICommandProcessor', $options->prefix); + $this->assertInstanceOf('Predis\Network\IConnectionCluster', $options->cluster); + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $options->profile); + $this->assertInstanceOf('Predis\IConnectionFactory', $options->connections); + } + + /** + * @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)); + } +} diff --git a/tests/Predis/Options/ClientPrefixTest.php b/tests/Predis/Options/ClientPrefixTest.php new file mode 100644 index 00000000..6fa93a4f --- /dev/null +++ b/tests/Predis/Options/ClientPrefixTest.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Options; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ClientPrefixTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testValidationReturnsCommandProcessor() + { + $value = 'prefix:'; + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientPrefix(); + + $return = $option->validate($options, $value); + + $this->assertInstanceOf('Predis\Commands\Processors\ICommandProcessor', $return); + $this->assertInstanceOf('Predis\Commands\Processors\KeyPrefixProcessor', $return); + $this->assertEquals($value, $return->getPrefix()); + } + + /** + * @group disconnected + */ + public function testDefaultReturnsNull() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientPrefix(); + + $this->assertNull($option->getDefault($options)); + } + + /** + * @group disconnected + */ + public function testInvokeReturnsCommandProcessorOrNull() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientPrefix(); + + $this->assertInstanceOf('Predis\Commands\Processors\ICommandProcessor', $option($options, 'prefix:')); + $this->assertNull($option($options, null)); + } +} diff --git a/tests/Predis/Options/ClientProfileTest.php b/tests/Predis/Options/ClientProfileTest.php new file mode 100644 index 00000000..c771aef6 --- /dev/null +++ b/tests/Predis/Options/ClientProfileTest.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Options; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Profiles\ServerProfile; +use Predis\Commands\Processors\KeyPrefixProcessor; + +/** + * + */ +class ClientProfileTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testValidationReturnsServerProfileWithStringValue() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientProfile(); + + $profile = $option->validate($options, '2.0'); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $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\Options\IClientOptions'); + $option = new ClientProfile(); + + $profile = $option->validate($options, $value); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile); + $this->assertEquals('2.0', $profile->getVersion()); + $this->assertNull($profile->getProcessor()); + } + + /** + * @group disconnected + */ + public function testValidationThrowsExceptionOnWrongInvalidArguments() + { + $this->setExpectedException('InvalidArgumentException'); + + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientProfile(); + + $option->validate($options, new \stdClass()); + } + + /** + * @group disconnected + */ + public function testDefaultReturnsDefaultServerProfile() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientProfile(); + + $profile = $option->getDefault($options); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile); + $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile); + $this->assertNull($profile->getProcessor()); + } + + /** + * @group disconnected + */ + public function testInvokeReturnsSpecifiedServerProfileOrDefault() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new ClientProfile(); + + $profile = $option($options, '2.0'); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile); + $this->assertEquals('2.0', $profile->getVersion()); + $this->assertNull($profile->getProcessor()); + + $profile = $option($options, null); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $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 testValidateSetsPrefixProcessorFromClientOptions() + { + $options = $this->getMock('Predis\Options\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->validate($options, '2.0'); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile); + $this->assertEquals('2.0', $profile->getVersion()); + $this->assertInstanceOf('Predis\Commands\Processors\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\Options\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\Profiles\IServerProfile', $profile); + $this->assertInstanceOf(get_class(ServerProfile::getDefault()), $profile); + $this->assertInstanceOf('Predis\Commands\Processors\KeyPrefixProcessor', $profile->getProcessor()); + $this->assertEquals('prefix:', $profile->getProcessor()->getPrefix()); + } + + /** + * @group disconnected + */ + public function testValidationDoesNotSetPrefixProcessorWhenValueIsProfileInstance() + { + $options = $this->getMock('Predis\Options\ClientOptions', array('__isset', '__get')); + $options->expects($this->never())->method('__isset'); + $options->expects($this->never())->method('__get'); + + $option = new ClientProfile(); + + $profile = $option->validate($options, ServerProfile::getDefault()); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile); + $this->assertNull($profile->getProcessor()); + } +} diff --git a/tests/Predis/Options/CustomOptionTest.php b/tests/Predis/Options/CustomOptionTest.php new file mode 100644 index 00000000..32869bf5 --- /dev/null +++ b/tests/Predis/Options/CustomOptionTest.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Options; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class CustomOptionTest extends StandardTestCase +{ + /** + * @group disconnected + * @expectedException InvalidArgumentException + */ + public function testConstructorAcceptsOnlyCallablesForValidate() + { + $option = new CustomOption(array('validate' => 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 testValidateWithoutCallbackReturnsValue() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new CustomOption(); + + $this->assertEquals('test', $option->validate($options, 'test')); + } + + /** + * @group disconnected + */ + public function testDefaultWithoutCallbackReturnsNull() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new CustomOption(); + + $this->assertNull($option->getDefault($options)); + } + + /** + * @group disconnected + */ + public function testInvokeCallsValidateCallback() + { + $value = 'test'; + + $options = $this->getMock('Predis\Options\IClientOptions'); + + $validate = $this->getMock('stdClass', array('__invoke')); + $validate->expects($this->once()) + ->method('__invoke') + ->with($this->isInstanceOf('Predis\Options\IClientOptions'), $value) + ->will($this->returnValue(true)); + + $default = $this->getMock('stdClass', array('__invoke')); + $default->expects($this->never())->method('__invoke'); + + $option = new CustomOption(array('validate' => $validate, 'default' => $default)); + + $this->assertTrue($option($options, $value)); + } + + /** + * @group disconnected + */ + public function testInvokeCallsDefaultCallback() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + + $validate = $this->getMock('stdClass', array('__invoke')); + $validate->expects($this->never())->method('__invoke'); + + $default = $this->getMock('stdClass', array('__invoke')); + $default->expects($this->once()) + ->method('__invoke') + ->with($this->isInstanceOf('Predis\Options\IClientOptions')) + ->will($this->returnValue(true)); + + $option = new CustomOption(array('validate' => $validate, 'default' => $default)); + + $this->assertTrue($option($options, null)); + } +} diff --git a/tests/Predis/Options/OptionTest.php b/tests/Predis/Options/OptionTest.php new file mode 100644 index 00000000..1eab1f11 --- /dev/null +++ b/tests/Predis/Options/OptionTest.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Options; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class OptionTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testValidationReturnsTheSameObject() + { + $value = new \stdClass(); + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new Option(); + + $this->assertSame($value, $option->validate($options, $value)); + } + + /** + * @group disconnected + */ + public function testDefaultReturnsNull() + { + $options = $this->getMock('Predis\Options\IClientOptions'); + $option = new Option(); + + $this->assertNull($option->getDefault($options)); + } + + /** + * @group disconnected + */ + public function testInvokePerformsValidationWhenValueIsSet() + { + $value = new \stdClass(); + $options = $this->getMock('Predis\Options\IClientOptions'); + + $option = $this->getMock('Predis\Options\Option', array('validate', 'getDefault')); + $option->expects($this->once()) + ->method('validate') + ->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\Options\IClientOptions'); + + $option = $this->getMock('Predis\Options\Option', array('validate', 'getDefault')); + $option->expects($this->never())->method('validate'); + $option->expects($this->once()) + ->method('getDefault') + ->with($options) + ->will($this->returnValue($expected)); + + $this->assertSame($expected, $option($options, null)); + } +} diff --git a/tests/Predis/Pipeline/PipelineContextTest.php b/tests/Predis/Pipeline/PipelineContextTest.php new file mode 100644 index 00000000..3e2b78cf --- /dev/null +++ b/tests/Predis/Pipeline/PipelineContextTest.php @@ -0,0 +1,420 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Pipeline; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; +use Predis\ClientException; +use Predis\Profiles\ServerProfile; + +/** + * + */ +class PipelineContextTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testConstructorWithoutOptions() + { + $client = new Client(); + $pipeline = new PipelineContext($client); + + $this->assertSame($client, $pipeline->getClient()); + $this->assertInstanceOf('Predis\Pipeline\StandardExecutor', $pipeline->getExecutor()); + } + + /** + * @group disconnected + */ + public function testConstructorWithOptions() + { + $client = new Client(); + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $pipeline = new PipelineContext($client, array('executor' => $executor)); + $this->assertSame($executor, $pipeline->getExecutor()); + + $pipeline = new PipelineContext($client, array('safe' => true)); + $this->assertInstanceOf('Predis\Pipeline\SafeExecutor', $pipeline->getExecutor()); + + $options = array('executor' => 'safe'); + $client = new Client($this->getMock('Predis\Network\IConnectionCluster')); + $pipeline = new PipelineContext($client, array('safe' => true)); + $this->assertInstanceOf('Predis\Pipeline\SafeClusterExecutor', $pipeline->getExecutor()); + } + + /** + * @group disconnected + */ + public function testCallDoesNotSendCommandsWithoutExecute() + { + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $executor->expects($this->never())->method('executor'); + + $pipeline = new PipelineContext(new Client(), array('executor' => $executor)); + + $pipeline->echo('one'); + $pipeline->echo('two'); + $pipeline->echo('three'); + } + + /** + * @group disconnected + */ + public function testCallReturnsPipelineForFluentInterface() + { + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $executor->expects($this->never())->method('executor'); + + $pipeline = new PipelineContext(new Client(), array('executor' => $executor)); + + $this->assertSame($pipeline, $pipeline->echo('one')); + $this->assertSame($pipeline, $pipeline->echo('one')->echo('two')->echo('three')); + } + + /** + * @group disconnected + */ + public function testExecuteCommandDoesNotSendCommandsWithoutExecute() + { + $profile = ServerProfile::getDefault(); + + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $executor->expects($this->never())->method('executor'); + + $pipeline = new PipelineContext(new Client(), array('executor' => $executor)); + + $pipeline->executeCommand($profile->createCommand('echo', array('one'))); + $pipeline->executeCommand($profile->createCommand('echo', array('two'))); + $pipeline->executeCommand($profile->createCommand('echo', array('three'))); + } + + /** + * @group disconnected + */ + public function testExecuteWithEmptyBuffer() + { + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $executor->expects($this->never())->method('executor'); + + $pipeline = new PipelineContext(new Client(), array('executor' => $executor)); + + $this->assertSame(array(), $pipeline->execute()); + } + + /** + * @group disconnected + */ + public function testExecuteWithFilledBuffer() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->exactly(3)) + ->method('writeCommand'); + $connection->expects($this->exactly(3)) + ->method('readResponse') + ->will($this->returnCallback($this->getReadCallback())); + + $pipeline = new PipelineContext(new Client($connection)); + + $pipeline->echo('one'); + $pipeline->echo('two'); + $pipeline->echo('three'); + + $pipeline->flushPipeline(); + + $this->assertSame(array('one', 'two', 'three'), $pipeline->execute()); + } + + /** + * @group disconnected + */ + public function testFlushWithFalseArgumentDiscardsBuffer() + { + $executor = $this->getMock('Predis\Pipeline\IPipelineExecutor'); + $executor->expects($this->never())->method('executor'); + + $pipeline = new PipelineContext(new Client(), array('executor' => $executor)); + + $pipeline->echo('one'); + $pipeline->echo('two'); + $pipeline->echo('three'); + + $pipeline->flushPipeline(false); + + $this->assertSame(array(), $pipeline->execute()); + } + + /** + * @group disconnected + */ + public function testFlushHandlesPartialBuffers() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->exactly(4)) + ->method('writeCommand'); + $connection->expects($this->exactly(4)) + ->method('readResponse') + ->will($this->returnCallback($this->getReadCallback())); + + $pipeline = new PipelineContext(new Client($connection)); + + $pipeline->echo('one'); + $pipeline->echo('two'); + $pipeline->flushPipeline(); + $pipeline->echo('three'); + $pipeline->echo('four'); + + $this->assertSame(array('one', 'two', 'three', 'four'), $pipeline->execute()); + } + + /** + * @group disconnected + */ + public function testExecuteAcceptsCallableArgument() + { + $test = $this; + $pipeline = new PipelineContext(new Client()); + + $callable = function($pipe) use($test, $pipeline) { + $test->assertSame($pipeline, $pipe); + $pipe->flushPipeline(false); + }; + + $pipeline->execute($callable); + } + + /** + * @group disconnected + * @expectedException InvalidArgumentException + */ + public function testExecuteDoesNotAcceptNonCallableArgument() + { + $noncallable = new \stdClass(); + + $pipeline = new PipelineContext(new Client()); + $pipeline->execute($noncallable); + } + + /** + * @group disconnected + * @expectedException Predis\ClientException + */ + public function testExecuteInsideCallableArgumentThrowsException() + { + $pipeline = new PipelineContext(new Client()); + + $pipeline->execute(function($pipe) { + $pipe->execute(); + }); + } + + /** + * @group disconnected + */ + public function testExecuteWithCallableArgumentRunsPipelineInCallable() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->exactly(4)) + ->method('writeCommand'); + $connection->expects($this->exactly(4)) + ->method('readResponse') + ->will($this->returnCallback($this->getReadCallback())); + + $pipeline = new PipelineContext(new Client($connection)); + + $replies = $pipeline->execute(function($pipe) { + $pipe->echo('one'); + $pipe->echo('two'); + $pipe->echo('three'); + $pipe->echo('four'); + }); + + $this->assertSame(array('one', 'two', 'three', 'four'), $replies); + } + + /** + * @group disconnected + */ + public function testExecuteWithCallableArgumentHandlesExceptions() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->never())->method('writeCommand'); + $connection->expects($this->never())->method('readResponse'); + + $pipeline = new PipelineContext(new Client($connection)); + + $exception = null; + $replies = null; + + try { + $replies = $pipeline->execute(function($pipe) { + $pipe->echo('one'); + throw new ClientException('TEST'); + $pipe->echo('two'); + }); + } + catch (\Exception $ex) { + $exception = $ex; + } + + $this->assertInstanceOf('Predis\ClientException', $exception); + $this->assertSame('TEST', $exception->getMessage()); + $this->assertNull($replies); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testIntegrationWithFluentInterface() + { + $pipeline = $this->getClient()->pipeline(); + + $results = $pipeline->echo('one') + ->echo('two') + ->echo('three') + ->execute(); + + $this->assertSame(array('one', 'two', 'three'), $results); + } + + /** + * @group connected + */ + public function testIntegrationWithCallableBlock() + { + $client = $this->getClient(); + + $results = $client->pipeline(function($pipe) { + $pipe->set('foo', 'bar'); + $pipe->get('foo'); + }); + + $this->assertSame(array(true, 'bar'), $results); + $this->assertTrue($client->exists('foo')); + } + + /** + * @group connected + */ + public function testIntegrationWithClientExceptionInCallableBlock() + { + $client = $this->getClient(); + + try { + $client->pipeline(function($pipe) { + $pipe->set('foo', 'bar'); + throw new ClientException('TEST'); + }); + } + catch (\Exception $ex) { + $exception = $ex; + } + + $this->assertInstanceOf('Predis\ClientException', $exception); + $this->assertSame('TEST', $exception->getMessage()); + $this->assertFalse($client->exists('foo')); + } + + /** + * @group connected + */ + public function testIntegrationWithServerExceptionInCallableBlock() + { + $client = $this->getClient(); + + try { + $client->pipeline(function($pipe) { + $pipe->set('foo', 'bar'); + // LPUSH on a string key fails, but won't stop + // the pipeline to send the commands. + $pipe->lpush('foo', 'bar'); + $pipe->set('hoge', 'piyo'); + }); + } + catch (\Exception $ex) { + $exception = $ex; + } + + $this->assertInstanceOf('Predis\ServerException', $exception); + $this->assertTrue($client->exists('foo')); + $this->assertTrue($client->exists('hoge')); + } + + /** + * @group connected + */ + public function testIntegrationWithServerErrorInCallableBlock() + { + $client = $this->getClient(array('throw_errors' => false)); + + $results = $client->pipeline(function($pipe) { + $pipe->set('foo', 'bar'); + $pipe->lpush('foo', 'bar'); // LPUSH on a string key fails. + $pipe->get('foo'); + }); + + $this->assertTrue($results[0]); + $this->assertInstanceOf('Predis\ResponseError', $results[1]); + $this->assertSame('bar', $results[2]); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a client instance connected to the specified Redis + * server instance to perform integration tests. + * + * @return array Additional connection parameters. + * @return Client client instance. + */ + protected function getClient(Array $parameters = array()) + { + $parameters = array_merge(array( + 'scheme' => 'tcp', + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'database' => REDIS_SERVER_DBNUM, + ), $parameters); + + $client = new Client($parameters, array('profile' => REDIS_SERVER_VERSION)); + + $client->connect(); + $client->flushdb(); + + return $client; + } + + /** + * Helper method that returns a callback used to emulate a reply + * to an ECHO command. + * + * @return \Closure + */ + protected function getReadCallback() + { + return function($command) { + if (($id = $command->getId()) !== 'ECHO') { + throw new \InvalidArgumentException("Expected ECHO, got {$id}"); + } + + list($echoed) = $command->getArguments(); + return $echoed; + }; + } +} diff --git a/tests/Predis/PredisExceptionTest.php b/tests/Predis/PredisExceptionTest.php new file mode 100644 index 00000000..4cfbc656 --- /dev/null +++ b/tests/Predis/PredisExceptionTest.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class PredisExceptionTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testExceptionMessage() + { + $message = 'Predis exception message'; + $exception = $this->getMockForAbstractClass('Predis\PredisException', array($message)); + + $this->setExpectedException('Predis\PredisException', $message); + + throw $exception; + } +} diff --git a/tests/Predis/Profiles/ServerProfileTest.php b/tests/Predis/Profiles/ServerProfileTest.php new file mode 100644 index 00000000..52606cfb --- /dev/null +++ b/tests/Predis/Profiles/ServerProfileTest.php @@ -0,0 +1,265 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Profiles; + +use \PHPUnit_Framework_TestCase as StandardTestCase; +use Predis\Commands\Processors\ProcessorChain; + +/** + * + */ +class ServerProfileTest extends StandardTestCase +{ + const DEFAULT_PROFILE_VERSION = '2.4'; + const DEVELOPMENT_PROFILE_VERSION = '2.6'; + + /** + * @group disconnected + */ + public function testGetVersion() + { + $profile = ServerProfile::get('2.0'); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile); + $this->assertEquals('2.0', $profile->getVersion()); + } + + /** + * @group disconnected + */ + public function testGetDefault() + { + $profile1 = ServerProfile::get(self::DEFAULT_PROFILE_VERSION); + $profile2 = ServerProfile::get('default'); + $profile3 = ServerProfile::getDefault(); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile1); + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile2); + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile3); + $this->assertEquals($profile1->getVersion(), $profile2->getVersion()); + $this->assertEquals($profile2->getVersion(), $profile3->getVersion()); + } + + /** + * @group disconnected + */ + public function testGetDevelopment() + { + $profile1 = ServerProfile::get('dev'); + $profile2 = ServerProfile::getDevelopment(); + + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile1); + $this->assertInstanceOf('Predis\Profiles\IServerProfile', $profile2); + $this->assertEquals(self::DEVELOPMENT_PROFILE_VERSION, $profile2->getVersion()); + } + + /** + * @group disconnected + * @expectedException Predis\ClientException + * @expectedExceptionMessage Unknown server profile: 1.0 + */ + public function testGetUndefinedProfile() + { + ServerProfile::get('1.0'); + } + + /** + * @group disconnected + */ + public function testDefineProfile() + { + $profileClass = get_class($this->getMock('Predis\Profiles\IServerProfile')); + + ServerProfile::define('mock', $profileClass); + + $this->assertInstanceOf($profileClass, ServerProfile::get('mock')); + } + + /** + * @group disconnected + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Cannot register 'stdClass' as it is not a valid profile class + */ + public function testDefineInvalidProfile() + { + ServerProfile::define('bogus', 'stdClass'); + } + + /** + * @group disconnected + */ + public function testToString() + { + $this->assertEquals('2.0', (string) ServerProfile::get('2.0')); + } + + /** + * @group disconnected + */ + public function testSupportCommand() + { + $profile = ServerProfile::getDefault(); + + $this->assertTrue($profile->supportsCommand('info')); + $this->assertTrue($profile->supportsCommand('INFO')); + + $this->assertFalse($profile->supportsCommand('unknown')); + $this->assertFalse($profile->supportsCommand('UNKNOWN')); + } + + /** + * @group disconnected + */ + public function testSupportCommands() + { + $profile = ServerProfile::getDefault(); + + $this->assertTrue($profile->supportsCommands(array('get', 'set'))); + $this->assertTrue($profile->supportsCommands(array('GET', 'SET'))); + + $this->assertFalse($profile->supportsCommands(array('get', 'unknown'))); + + $this->assertFalse($profile->supportsCommands(array('unknown1', 'unknown2'))); + } + + /** + * @group disconnected + */ + public function testGetCommandClass() + { + $profile = ServerProfile::getDefault(); + + $this->assertSame('Predis\Commands\ConnectionPing', $profile->getCommandClass('ping')); + $this->assertSame('Predis\Commands\ConnectionPing', $profile->getCommandClass('PING')); + + $this->assertNull($profile->getCommandClass('unknown')); + $this->assertNull($profile->getCommandClass('UNKNOWN')); + } + + /** + * @group disconnected + */ + public function testCreateCommandWithoutArguments() + { + $profile = ServerProfile::getDefault(); + + $command = $profile->createCommand('info'); + $this->assertInstanceOf('Predis\Commands\ICommand', $command); + $this->assertEquals('INFO', $command->getId()); + $this->assertEquals(array(), $command->getArguments()); + } + + /** + * @group disconnected + */ + public function testCreateCommandWithArguments() + { + $profile = ServerProfile::getDefault(); + $arguments = array('foo', 'bar'); + + $command = $profile->createCommand('set', $arguments); + $this->assertInstanceOf('Predis\Commands\ICommand', $command); + $this->assertEquals('SET', $command->getId()); + $this->assertEquals($arguments, $command->getArguments()); + } + + /** + * @group disconnected + * @expectedException Predis\ClientException + * @expectedExceptionMessage 'unknown' is not a registered Redis command + */ + public function testCreateUndefinedCommand() + { + $profile = ServerProfile::getDefault(); + $profile->createCommand('unknown'); + } + + /** + * @group disconnected + */ + public function testGetDefaultProcessor() + { + $profile = ServerProfile::getDefault(); + + $this->assertNull($profile->getProcessor()); + } + + /** + * @group disconnected + */ + public function testSetProcessor() + { + $processor = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + + $profile = ServerProfile::getDefault(); + $profile->setProcessor($processor); + + $this->assertSame($processor, $profile->getProcessor()); + } + + /** + * @group disconnected + */ + public function testSetAndUnsetProcessor() + { + $processor = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + $profile = ServerProfile::getDefault(); + + $profile->setProcessor($processor); + $this->assertSame($processor, $profile->getProcessor()); + + $profile->setProcessor(null); + $this->assertNull($profile->getProcessor()); + } + + /** + * @group disconnected + * @todo Could it be that objects passed to the return callback of a mocked + * method are cloned instead of being passed by reference? + */ + public function testSingleProcessor() + { + $argsRef = null; + + $processor = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + $processor->expects($this->once()) + ->method('process') + ->with($this->isInstanceOf('Predis\Commands\ICommand')) + ->will($this->returnCallback(function($cmd) use(&$argsRef) { + $cmd->setRawArguments($argsRef = array_map('strtoupper', $cmd->getArguments())); + })); + + $profile = ServerProfile::getDefault(); + $profile->setProcessor($processor); + $command = $profile->createCommand('set', array('foo', 'bar')); + + $this->assertSame(array('FOO', 'BAR'), $argsRef); + } + + /** + * @group disconnected + */ + public function testChainOfProcessors() + { + $processor = $this->getMock('Predis\Commands\Processors\ICommandProcessor'); + $processor->expects($this->exactly(2)) + ->method('process'); + + $chain = new ProcessorChain(); + $chain->add($processor); + $chain->add($processor); + + $profile = ServerProfile::getDefault(); + $profile->setProcessor($chain); + $profile->createCommand('info'); + } +} diff --git a/tests/Predis/Profiles/ServerVersion12Test.php b/tests/Predis/Profiles/ServerVersion12Test.php new file mode 100644 index 00000000..ebfdf98c --- /dev/null +++ b/tests/Predis/Profiles/ServerVersion12Test.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Profiles; + +/** + * + */ +class ServerVersion12Test extends ServerVersionTestCase +{ + /** + * {@inheritdoc} + */ + public function getProfileInstance() + { + return new ServerVersion12(); + } + + /** + * {@inheritdoc} + */ + public function getExpectedVersion() + { + return '1.2'; + } + + /** + * {@inheritdoc} + */ + public function getExpectedCommands() + { + return array( + 0 => 'exists', + 1 => 'del', + 2 => 'type', + 3 => 'keys', + 4 => 'randomkey', + 5 => 'rename', + 6 => 'renamenx', + 7 => 'expire', + 8 => 'expireat', + 9 => 'ttl', + 10 => 'move', + 11 => 'sort', + 12 => 'set', + 13 => 'setnx', + 14 => 'mset', + 15 => 'msetnx', + 16 => 'get', + 17 => 'mget', + 18 => 'getset', + 19 => 'incr', + 20 => 'incrby', + 21 => 'decr', + 22 => 'decrby', + 23 => 'rpush', + 24 => 'lpush', + 25 => 'llen', + 26 => 'lrange', + 27 => 'ltrim', + 28 => 'lindex', + 29 => 'lset', + 30 => 'lrem', + 31 => 'lpop', + 32 => 'rpop', + 33 => 'rpoplpush', + 34 => 'sadd', + 35 => 'srem', + 36 => 'spop', + 37 => 'smove', + 38 => 'scard', + 39 => 'sismember', + 40 => 'sinter', + 41 => 'sinterstore', + 42 => 'sunion', + 43 => 'sunionstore', + 44 => 'sdiff', + 45 => 'sdiffstore', + 46 => 'smembers', + 47 => 'srandmember', + 48 => 'zadd', + 49 => 'zincrby', + 50 => 'zrem', + 51 => 'zrange', + 52 => 'zrevrange', + 53 => 'zrangebyscore', + 54 => 'zcard', + 55 => 'zscore', + 56 => 'zremrangebyscore', + 57 => 'ping', + 58 => 'auth', + 59 => 'select', + 60 => 'echo', + 61 => 'quit', + 62 => 'info', + 63 => 'slaveof', + 64 => 'monitor', + 65 => 'dbsize', + 66 => 'flushdb', + 67 => 'flushall', + 68 => 'save', + 69 => 'bgsave', + 70 => 'lastsave', + 71 => 'shutdown', + 72 => 'bgrewriteaof', + ); + } +} diff --git a/tests/Predis/Profiles/ServerVersion20Test.php b/tests/Predis/Profiles/ServerVersion20Test.php new file mode 100644 index 00000000..02d17d1e --- /dev/null +++ b/tests/Predis/Profiles/ServerVersion20Test.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Profiles; + +/** + * + */ +class ServerVersion20Test extends ServerVersionTestCase +{ + /** + * {@inheritdoc} + */ + public function getProfileInstance() + { + return new ServerVersion20(); + } + + /** + * {@inheritdoc} + */ + public function getExpectedVersion() + { + return '2.0'; + } + + /** + * {@inheritdoc} + */ + public function getExpectedCommands() + { + return array( + 0 => 'exists', + 1 => 'del', + 2 => 'type', + 3 => 'keys', + 4 => 'randomkey', + 5 => 'rename', + 6 => 'renamenx', + 7 => 'expire', + 8 => 'expireat', + 9 => 'ttl', + 10 => 'move', + 11 => 'sort', + 12 => 'set', + 13 => 'setnx', + 14 => 'mset', + 15 => 'msetnx', + 16 => 'get', + 17 => 'mget', + 18 => 'getset', + 19 => 'incr', + 20 => 'incrby', + 21 => 'decr', + 22 => 'decrby', + 23 => 'rpush', + 24 => 'lpush', + 25 => 'llen', + 26 => 'lrange', + 27 => 'ltrim', + 28 => 'lindex', + 29 => 'lset', + 30 => 'lrem', + 31 => 'lpop', + 32 => 'rpop', + 33 => 'rpoplpush', + 34 => 'sadd', + 35 => 'srem', + 36 => 'spop', + 37 => 'smove', + 38 => 'scard', + 39 => 'sismember', + 40 => 'sinter', + 41 => 'sinterstore', + 42 => 'sunion', + 43 => 'sunionstore', + 44 => 'sdiff', + 45 => 'sdiffstore', + 46 => 'smembers', + 47 => 'srandmember', + 48 => 'zadd', + 49 => 'zincrby', + 50 => 'zrem', + 51 => 'zrange', + 52 => 'zrevrange', + 53 => 'zrangebyscore', + 54 => 'zcard', + 55 => 'zscore', + 56 => 'zremrangebyscore', + 57 => 'ping', + 58 => 'auth', + 59 => 'select', + 60 => 'echo', + 61 => 'quit', + 62 => 'info', + 63 => 'slaveof', + 64 => 'monitor', + 65 => 'dbsize', + 66 => 'flushdb', + 67 => 'flushall', + 68 => 'save', + 69 => 'bgsave', + 70 => 'lastsave', + 71 => 'shutdown', + 72 => 'bgrewriteaof', + 73 => 'setex', + 74 => 'append', + 75 => 'substr', + 76 => 'blpop', + 77 => 'brpop', + 78 => 'zunionstore', + 79 => 'zinterstore', + 80 => 'zcount', + 81 => 'zrank', + 82 => 'zrevrank', + 83 => 'zremrangebyrank', + 84 => 'hset', + 85 => 'hsetnx', + 86 => 'hmset', + 87 => 'hincrby', + 88 => 'hget', + 89 => 'hmget', + 90 => 'hdel', + 91 => 'hexists', + 92 => 'hlen', + 93 => 'hkeys', + 94 => 'hvals', + 95 => 'hgetall', + 96 => 'multi', + 97 => 'exec', + 98 => 'discard', + 99 => 'subscribe', + 100 => 'unsubscribe', + 101 => 'psubscribe', + 102 => 'punsubscribe', + 103 => 'publish', + 104 => 'config', + ); + } +} diff --git a/tests/Predis/Profiles/ServerVersion22Test.php b/tests/Predis/Profiles/ServerVersion22Test.php new file mode 100644 index 00000000..0837e648 --- /dev/null +++ b/tests/Predis/Profiles/ServerVersion22Test.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Profiles; + +/** + * + */ +class ServerVersion22Test extends ServerVersionTestCase +{ + /** + * {@inheritdoc} + */ + public function getProfileInstance() + { + return new ServerVersion22(); + } + + /** + * {@inheritdoc} + */ + public function getExpectedVersion() + { + return '2.2'; + } + + /** + * {@inheritdoc} + */ + public function getExpectedCommands() + { + return array( + 0 => 'exists', + 1 => 'del', + 2 => 'type', + 3 => 'keys', + 4 => 'randomkey', + 5 => 'rename', + 6 => 'renamenx', + 7 => 'expire', + 8 => 'expireat', + 9 => 'ttl', + 10 => 'move', + 11 => 'sort', + 12 => 'set', + 13 => 'setnx', + 14 => 'mset', + 15 => 'msetnx', + 16 => 'get', + 17 => 'mget', + 18 => 'getset', + 19 => 'incr', + 20 => 'incrby', + 21 => 'decr', + 22 => 'decrby', + 23 => 'rpush', + 24 => 'lpush', + 25 => 'llen', + 26 => 'lrange', + 27 => 'ltrim', + 28 => 'lindex', + 29 => 'lset', + 30 => 'lrem', + 31 => 'lpop', + 32 => 'rpop', + 33 => 'rpoplpush', + 34 => 'sadd', + 35 => 'srem', + 36 => 'spop', + 37 => 'smove', + 38 => 'scard', + 39 => 'sismember', + 40 => 'sinter', + 41 => 'sinterstore', + 42 => 'sunion', + 43 => 'sunionstore', + 44 => 'sdiff', + 45 => 'sdiffstore', + 46 => 'smembers', + 47 => 'srandmember', + 48 => 'zadd', + 49 => 'zincrby', + 50 => 'zrem', + 51 => 'zrange', + 52 => 'zrevrange', + 53 => 'zrangebyscore', + 54 => 'zcard', + 55 => 'zscore', + 56 => 'zremrangebyscore', + 57 => 'ping', + 58 => 'auth', + 59 => 'select', + 60 => 'echo', + 61 => 'quit', + 62 => 'info', + 63 => 'slaveof', + 64 => 'monitor', + 65 => 'dbsize', + 66 => 'flushdb', + 67 => 'flushall', + 68 => 'save', + 69 => 'bgsave', + 70 => 'lastsave', + 71 => 'shutdown', + 72 => 'bgrewriteaof', + 73 => 'setex', + 74 => 'append', + 75 => 'substr', + 76 => 'blpop', + 77 => 'brpop', + 78 => 'zunionstore', + 79 => 'zinterstore', + 80 => 'zcount', + 81 => 'zrank', + 82 => 'zrevrank', + 83 => 'zremrangebyrank', + 84 => 'hset', + 85 => 'hsetnx', + 86 => 'hmset', + 87 => 'hincrby', + 88 => 'hget', + 89 => 'hmget', + 90 => 'hdel', + 91 => 'hexists', + 92 => 'hlen', + 93 => 'hkeys', + 94 => 'hvals', + 95 => 'hgetall', + 96 => 'multi', + 97 => 'exec', + 98 => 'discard', + 99 => 'subscribe', + 100 => 'unsubscribe', + 101 => 'psubscribe', + 102 => 'punsubscribe', + 103 => 'publish', + 104 => 'config', + 105 => 'persist', + 106 => 'strlen', + 107 => 'setrange', + 108 => 'getrange', + 109 => 'setbit', + 110 => 'getbit', + 111 => 'rpushx', + 112 => 'lpushx', + 113 => 'linsert', + 114 => 'brpoplpush', + 115 => 'zrevrangebyscore', + 116 => 'watch', + 117 => 'unwatch', + 118 => 'object', + 119 => 'slowlog', + ); + } +} diff --git a/tests/Predis/Profiles/ServerVersion24Test.php b/tests/Predis/Profiles/ServerVersion24Test.php new file mode 100644 index 00000000..239d5b09 --- /dev/null +++ b/tests/Predis/Profiles/ServerVersion24Test.php @@ -0,0 +1,164 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Profiles; + +/** + * + */ +class ServerVersion24Test extends ServerVersionTestCase +{ + /** + * {@inheritdoc} + */ + public function getProfileInstance() + { + return new ServerVersion24(); + } + + /** + * {@inheritdoc} + */ + public function getExpectedVersion() + { + return '2.4'; + } + + /** + * {@inheritdoc} + */ + public function getExpectedCommands() + { + return array( + 0 => 'exists', + 1 => 'del', + 2 => 'type', + 3 => 'keys', + 4 => 'randomkey', + 5 => 'rename', + 6 => 'renamenx', + 7 => 'expire', + 8 => 'expireat', + 9 => 'ttl', + 10 => 'move', + 11 => 'sort', + 12 => 'set', + 13 => 'setnx', + 14 => 'mset', + 15 => 'msetnx', + 16 => 'get', + 17 => 'mget', + 18 => 'getset', + 19 => 'incr', + 20 => 'incrby', + 21 => 'decr', + 22 => 'decrby', + 23 => 'rpush', + 24 => 'lpush', + 25 => 'llen', + 26 => 'lrange', + 27 => 'ltrim', + 28 => 'lindex', + 29 => 'lset', + 30 => 'lrem', + 31 => 'lpop', + 32 => 'rpop', + 33 => 'rpoplpush', + 34 => 'sadd', + 35 => 'srem', + 36 => 'spop', + 37 => 'smove', + 38 => 'scard', + 39 => 'sismember', + 40 => 'sinter', + 41 => 'sinterstore', + 42 => 'sunion', + 43 => 'sunionstore', + 44 => 'sdiff', + 45 => 'sdiffstore', + 46 => 'smembers', + 47 => 'srandmember', + 48 => 'zadd', + 49 => 'zincrby', + 50 => 'zrem', + 51 => 'zrange', + 52 => 'zrevrange', + 53 => 'zrangebyscore', + 54 => 'zcard', + 55 => 'zscore', + 56 => 'zremrangebyscore', + 57 => 'ping', + 58 => 'auth', + 59 => 'select', + 60 => 'echo', + 61 => 'quit', + 62 => 'info', + 63 => 'slaveof', + 64 => 'monitor', + 65 => 'dbsize', + 66 => 'flushdb', + 67 => 'flushall', + 68 => 'save', + 69 => 'bgsave', + 70 => 'lastsave', + 71 => 'shutdown', + 72 => 'bgrewriteaof', + 73 => 'setex', + 74 => 'append', + 75 => 'substr', + 76 => 'blpop', + 77 => 'brpop', + 78 => 'zunionstore', + 79 => 'zinterstore', + 80 => 'zcount', + 81 => 'zrank', + 82 => 'zrevrank', + 83 => 'zremrangebyrank', + 84 => 'hset', + 85 => 'hsetnx', + 86 => 'hmset', + 87 => 'hincrby', + 88 => 'hget', + 89 => 'hmget', + 90 => 'hdel', + 91 => 'hexists', + 92 => 'hlen', + 93 => 'hkeys', + 94 => 'hvals', + 95 => 'hgetall', + 96 => 'multi', + 97 => 'exec', + 98 => 'discard', + 99 => 'subscribe', + 100 => 'unsubscribe', + 101 => 'psubscribe', + 102 => 'punsubscribe', + 103 => 'publish', + 104 => 'config', + 105 => 'persist', + 106 => 'strlen', + 107 => 'setrange', + 108 => 'getrange', + 109 => 'setbit', + 110 => 'getbit', + 111 => 'rpushx', + 112 => 'lpushx', + 113 => 'linsert', + 114 => 'brpoplpush', + 115 => 'zrevrangebyscore', + 116 => 'watch', + 117 => 'unwatch', + 118 => 'object', + 119 => 'slowlog', + 120 => 'client', + ); + } +} diff --git a/tests/Predis/Profiles/ServerVersionNextTest.php b/tests/Predis/Profiles/ServerVersionNextTest.php new file mode 100644 index 00000000..76679bd2 --- /dev/null +++ b/tests/Predis/Profiles/ServerVersionNextTest.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Profiles; + +/** + * + */ +class ServerVersionNextTest extends ServerVersionTestCase +{ + /** + * {@inheritdoc} + */ + public function getProfileInstance() + { + return new ServerVersionNext(); + } + + /** + * {@inheritdoc} + */ + public function getExpectedVersion() + { + return '2.6'; + } + + /** + * {@inheritdoc} + */ + public function getExpectedCommands() + { + return array( + 0 => 'exists', + 1 => 'del', + 2 => 'type', + 3 => 'keys', + 4 => 'randomkey', + 5 => 'rename', + 6 => 'renamenx', + 7 => 'expire', + 8 => 'expireat', + 9 => 'ttl', + 10 => 'move', + 11 => 'sort', + 12 => 'set', + 13 => 'setnx', + 14 => 'mset', + 15 => 'msetnx', + 16 => 'get', + 17 => 'mget', + 18 => 'getset', + 19 => 'incr', + 20 => 'incrby', + 21 => 'decr', + 22 => 'decrby', + 23 => 'rpush', + 24 => 'lpush', + 25 => 'llen', + 26 => 'lrange', + 27 => 'ltrim', + 28 => 'lindex', + 29 => 'lset', + 30 => 'lrem', + 31 => 'lpop', + 32 => 'rpop', + 33 => 'rpoplpush', + 34 => 'sadd', + 35 => 'srem', + 36 => 'spop', + 37 => 'smove', + 38 => 'scard', + 39 => 'sismember', + 40 => 'sinter', + 41 => 'sinterstore', + 42 => 'sunion', + 43 => 'sunionstore', + 44 => 'sdiff', + 45 => 'sdiffstore', + 46 => 'smembers', + 47 => 'srandmember', + 48 => 'zadd', + 49 => 'zincrby', + 50 => 'zrem', + 51 => 'zrange', + 52 => 'zrevrange', + 53 => 'zrangebyscore', + 54 => 'zcard', + 55 => 'zscore', + 56 => 'zremrangebyscore', + 57 => 'ping', + 58 => 'auth', + 59 => 'select', + 60 => 'echo', + 61 => 'quit', + 62 => 'info', + 63 => 'slaveof', + 64 => 'monitor', + 65 => 'dbsize', + 66 => 'flushdb', + 67 => 'flushall', + 68 => 'save', + 69 => 'bgsave', + 70 => 'lastsave', + 71 => 'shutdown', + 72 => 'bgrewriteaof', + 73 => 'setex', + 74 => 'append', + 75 => 'substr', + 76 => 'blpop', + 77 => 'brpop', + 78 => 'zunionstore', + 79 => 'zinterstore', + 80 => 'zcount', + 81 => 'zrank', + 82 => 'zrevrank', + 83 => 'zremrangebyrank', + 84 => 'hset', + 85 => 'hsetnx', + 86 => 'hmset', + 87 => 'hincrby', + 88 => 'hget', + 89 => 'hmget', + 90 => 'hdel', + 91 => 'hexists', + 92 => 'hlen', + 93 => 'hkeys', + 94 => 'hvals', + 95 => 'hgetall', + 96 => 'multi', + 97 => 'exec', + 98 => 'discard', + 99 => 'subscribe', + 100 => 'unsubscribe', + 101 => 'psubscribe', + 102 => 'punsubscribe', + 103 => 'publish', + 104 => 'config', + 105 => 'persist', + 106 => 'strlen', + 107 => 'setrange', + 108 => 'getrange', + 109 => 'setbit', + 110 => 'getbit', + 111 => 'rpushx', + 112 => 'lpushx', + 113 => 'linsert', + 114 => 'brpoplpush', + 115 => 'zrevrangebyscore', + 116 => 'watch', + 117 => 'unwatch', + 118 => 'object', + 119 => 'slowlog', + 120 => 'client', + 121 => 'pttl', + 122 => 'pexpire', + 123 => 'pexpireat', + 124 => 'psetex', + 125 => 'incrbyfloat', + 126 => 'hincrbyfloat', + 127 => 'eval', + 128 => 'evalsha', + 129 => 'script', + ); + } +} diff --git a/tests/Predis/Protocol/ProtocolExceptionTest.php b/tests/Predis/Protocol/ProtocolExceptionTest.php new file mode 100644 index 00000000..0e970d33 --- /dev/null +++ b/tests/Predis/Protocol/ProtocolExceptionTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Protocol; + +require_once __DIR__.'/../CommunicationExceptionTest.php'; + +use Predis\CommunicationExceptionTest; +use Predis\Network\IConnectionSingle; + +/** + * + */ +class ProtocolExceptionTest extends CommunicationExceptionTest +{ + /** + * {@inheritdoc} + */ + protected function getException(IConnectionSingle $connection, $message, $code = 0, \Exception $inner = null) + { + return new ProtocolException($connection, $message, $code, $inner); + } +} diff --git a/tests/Predis/PubSub/DispatcherLoopTest.php b/tests/Predis/PubSub/DispatcherLoopTest.php new file mode 100644 index 00000000..7c646762 --- /dev/null +++ b/tests/Predis/PubSub/DispatcherLoopTest.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\PubSub; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; +use Predis\Profiles\ServerProfile; + +/** + * @group realm-pubsub + */ +class DispatcherLoopTest extends StandardTestCase +{ + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testDispatcherLoopAgainstRedisServer() + { + $parameters = array( + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'database' => REDIS_SERVER_DBNUM, + // Prevents suite from handing on broken test + 'read_write_timeout' => 2, + ); + + $producer = new Client($parameters, REDIS_SERVER_VERSION); + $producer->connect(); + + $consumer = new Client($parameters, REDIS_SERVER_VERSION); + $consumer->connect(); + + $dispatcher = new DispatcherLoop($consumer); + + $function01 = $this->getMock('stdClass', array('__invoke')); + $function01->expects($this->exactly(2)) + ->method('__invoke') + ->with($this->logicalOr( + $this->equalTo('01:argument'), + $this->equalTo('01:quit') + )) + ->will($this->returnCallback(function($arg) use($dispatcher) { + if ($arg === '01:quit') { + $dispatcher->stop(); + } + })); + + $function02 = $this->getMock('stdClass', array('__invoke')); + $function02->expects($this->once()) + ->method('__invoke') + ->with('02:argument'); + + $function03 = $this->getMock('stdClass', array('__invoke')); + $function03->expects($this->never()) + ->method('__invoke'); + + $dispatcher->attachCallback('function:01', $function01); + $dispatcher->attachCallback('function:02', $function02); + $dispatcher->attachCallback('function:03', $function03); + + $producer->publish('function:01', '01:argument'); + $producer->publish('function:02', '02:argument'); + $producer->publish('function:01', '01:quit'); + + $dispatcher->run(); + + $this->assertTrue($consumer->ping()); + } +} diff --git a/tests/Predis/PubSub/PubSubContextTest.php b/tests/Predis/PubSub/PubSubContextTest.php new file mode 100644 index 00000000..e398fb30 --- /dev/null +++ b/tests/Predis/PubSub/PubSubContextTest.php @@ -0,0 +1,294 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\PubSub; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; +use Predis\Profiles\ServerProfile; + +/** + * @group realm-pubsub + */ +class PubSubContextTest extends StandardTestCase +{ + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The current profile does not support PUB/SUB related commands + */ + public function testPubSubContextRequirePubSubRelatedCommand() + { + $profile = $this->getMock('Predis\Profiles\IServerProfile'); + $profile->expects($this->any()) + ->method('supportsCommands') + ->will($this->returnValue(false)); + + $client = new Client(null, array('profile' => $profile)); + $pubsub = new PubSubContext($client); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage Cannot initialize a PUB/SUB context over a cluster of connections + */ + public function testPubSubContextDoesNotWorkOnClusters() + { + $cluster = $this->getMock('Predis\Network\IConnectionCluster'); + + $client = new Client($cluster); + $pubsub = new PubSubContext($client); + } + + /** + * @group disconnected + */ + public function testConstructorWithoutSubscriptionsDoesNotOpenContext() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + $client = $this->getMock('Predis\Client', array('executeCommand'), array($connection)); + $client->expects($this->never())->method('executeCommand'); + + $pubsub = new PubSubContext($client); + } + + /** + * @group disconnected + */ + public function testConstructorWithSubscriptionsOpensContext() + { + $profile = ServerProfile::get(REDIS_SERVER_VERSION); + + $cmdSubscribe = $profile->createCommand('subscribe', array('channel:foo')); + $cmdPsubscribe = $profile->createCommand('psubscribe', array('channels:*')); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->exactly(2))->method('writeCommand'); + + $client = $this->getMock('Predis\Client', array('createCommand', 'writeCommand'), array($connection)); + $client->expects($this->exactly(2)) + ->method('createCommand') + ->with($this->logicalOr($this->equalTo('subscribe'), $this->equalTo('psubscribe'))) + ->will($this->returnCallback(function($id, $args) use($profile) { + return $profile->createCommand($id, $args); + })); + + $options = array('subscribe' => 'channel:foo', 'psubscribe' => 'channels:*'); + $pubsub = new PubSubContext($client, $options); + } + + /** + * @group disconnected + */ + public function testClosingContextWithTrueClosesConnection() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + $client = $this->getMock('Predis\Client', array('disconnect'), array($connection)); + $client->expects($this->exactly(1))->method('disconnect'); + + $pubsub = new PubSubContext($client, array('subscribe' => 'channel:foo')); + + $connection->expects($this->never())->method('writeCommand'); + + $pubsub->closeContext(true); + } + + /** + * @group disconnected + */ + public function testClosingContextWithFalseSendsUnsubscriptions() + { + $profile = ServerProfile::get(REDIS_SERVER_VERSION); + $classUnsubscribe = $profile->getCommandClass('unsubscribe'); + $classPunsubscribe = $profile->getCommandClass('punsubscribe'); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + + $client = $this->getMock('Predis\Client', array('disconnect'), array($connection)); + + $options = array('subscribe' => 'channel:foo', 'psubscribe' => 'channels:*'); + $pubsub = new PubSubContext($client, $options); + + $connection->expects($this->exactly(2)) + ->method('writeCommand') + ->with($this->logicalOr( + $this->isInstanceOf($classUnsubscribe), + $this->isInstanceOf($classPunsubscribe) + )); + + $pubsub->closeContext(false); + } + + /** + * @group disconnected + */ + public function testIsNotValidWhenNotSubscribed() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $client = $this->getMock('Predis\Client', array('disconnect'), array($connection)); + + $pubsub = new PubSubContext($client); + + $this->assertFalse($pubsub->valid()); + $this->assertNull($pubsub->next()); + } + + /** + * @group disconnected + */ + public function testReadsMessageFromConnection() + { + $rawmessage = array('message', 'channel:foo', 'message from channel'); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage)); + + $client = new Client($connection); + $pubsub = new PubSubContext($client, array('subscribe' => 'channel:foo')); + + $message = $pubsub->current(); + $this->assertSame('message', $message->kind); + $this->assertSame('channel:foo', $message->channel); + $this->assertSame('message from channel', $message->payload); + } + + /** + * @group disconnected + */ + public function testReadsPmessageFromConnection() + { + $rawmessage = array('pmessage', 'channel:*', 'channel:foo', 'message from channel'); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage)); + + $client = new Client($connection); + $pubsub = new PubSubContext($client, array('psubscribe' => 'channel:*')); + + $message = $pubsub->current(); + $this->assertSame('pmessage', $message->kind); + $this->assertSame('channel:*', $message->pattern); + $this->assertSame('channel:foo', $message->channel); + $this->assertSame('message from channel', $message->payload); + } + + /** + * @group disconnected + */ + public function testReadsSubscriptionMessageFromConnection() + { + $rawmessage = array('subscribe', 'channel:foo', 1); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage)); + + $client = new Client($connection); + $pubsub = new PubSubContext($client, array('subscribe' => 'channel:foo')); + + $message = $pubsub->current(); + $this->assertSame('subscribe', $message->kind); + $this->assertSame('channel:foo', $message->channel); + $this->assertSame(1, $message->payload); + } + + /** + * @group disconnected + */ + public function testReadsUnsubscriptionMessageFromConnection() + { + $rawmessage = array('unsubscribe', 'channel:foo', 1); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage)); + + $client = new Client($connection); + $pubsub = new PubSubContext($client, array('subscribe' => 'channel:foo')); + + $message = $pubsub->current(); + $this->assertSame('unsubscribe', $message->kind); + $this->assertSame('channel:foo', $message->channel); + $this->assertSame(1, $message->payload); + } + + /** + * @group disconnected + */ + public function testUnsubscriptionMessageWithZeroChannelCountInvalidatesContext() + { + $rawmessage = array('unsubscribe', 'channel:foo', 0); + + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage)); + + $client = new Client($connection); + $pubsub = new PubSubContext($client, array('subscribe' => 'channel:foo')); + + $this->assertTrue($pubsub->valid()); + + $message = $pubsub->current(); + $this->assertSame('unsubscribe', $message->kind); + $this->assertSame('channel:foo', $message->channel); + $this->assertSame(0, $message->payload); + + $this->assertFalse($pubsub->valid()); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testPubSubAgainstRedisServer() + { + $parameters = array( + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'database' => REDIS_SERVER_DBNUM, + // Prevents suite from handing on broken test + 'read_write_timeout' => 2, + ); + + $messages = array(); + + $producer = new Client($parameters, REDIS_SERVER_VERSION); + $producer->connect(); + + $consumer = new Client($parameters, REDIS_SERVER_VERSION); + $consumer->connect(); + + $pubsub = new PubSubContext($consumer); + $pubsub->subscribe('channel:foo'); + + $producer->publish('channel:foo', 'message1'); + $producer->publish('channel:foo', 'message2'); + $producer->publish('channel:foo', 'QUIT'); + + foreach ($pubsub as $message) { + if ($message->kind !== 'message') { + continue; + } + $messages[] = ($payload = $message->payload); + if ($payload === 'QUIT') { + $pubsub->closeContext(); + } + } + + $this->assertSame(array('message1', 'message2', 'QUIT'), $messages); + $this->assertFalse($pubsub->valid()); + $this->assertTrue($consumer->ping()); + } +} diff --git a/tests/Predis/ResponseErrorTest.php b/tests/Predis/ResponseErrorTest.php new file mode 100644 index 00000000..560534d5 --- /dev/null +++ b/tests/Predis/ResponseErrorTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ResponseErrorTest extends StandardTestCase +{ + const ERR_WRONG_KEY_TYPE = 'ERR Operation against a key holding the wrong kind of value'; + + /** + * @group disconnected + */ + public function testResponseErrorClass() + { + $error = new ResponseError(self::ERR_WRONG_KEY_TYPE); + + $this->assertInstanceOf('Predis\IRedisServerError', $error); + $this->assertInstanceOf('Predis\IReplyObject', $error); + } + + /** + * @group disconnected + */ + public function testErrorMessage() + { + $error = new ResponseError(self::ERR_WRONG_KEY_TYPE); + + $this->assertEquals(self::ERR_WRONG_KEY_TYPE, $error->getMessage()); + } + + /** + * @group disconnected + */ + public function testErrorType() + { + $exception = new ResponseError(self::ERR_WRONG_KEY_TYPE); + + $this->assertEquals('ERR', $exception->getErrorType()); + } + + /** + * @group disconnected + */ + public function testToString() + { + $error = new ResponseError(self::ERR_WRONG_KEY_TYPE); + + $this->assertEquals(self::ERR_WRONG_KEY_TYPE, (string) $error); + } +} diff --git a/tests/Predis/ResponseQueuedTest.php b/tests/Predis/ResponseQueuedTest.php new file mode 100644 index 00000000..c88b6865 --- /dev/null +++ b/tests/Predis/ResponseQueuedTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ResponseQueuedTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testResponseQueuedClass() + { + $queued = new ResponseQueued(); + + $this->assertInstanceOf('Predis\IReplyObject', $queued); + } + + /** + * @group disconnected + */ + public function testToString() + { + $queued = new ResponseQueued(); + + $this->assertEquals('QUEUED', (string) $queued); + } + + /** + * @group disconnected + */ + public function testQueuedProperty() + { + $queued = new ResponseQueued(); + + $this->assertTrue(isset($queued->queued)); + $this->assertTrue($queued->queued); + } +} diff --git a/tests/Predis/ServerExceptionTest.php b/tests/Predis/ServerExceptionTest.php new file mode 100644 index 00000000..85cf5023 --- /dev/null +++ b/tests/Predis/ServerExceptionTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +/** + * + */ +class ServerExceptionTest extends StandardTestCase +{ + const ERR_WRONG_KEY_TYPE = 'ERR Operation against a key holding the wrong kind of value'; + + /** + * @group disconnected + */ + public function testExceptionMessage() + { + $this->setExpectedException('Predis\ServerException', self::ERR_WRONG_KEY_TYPE); + + throw new ServerException(self::ERR_WRONG_KEY_TYPE); + } + + /** + * @group disconnected + */ + public function testExceptionClass() + { + $exception = new ServerException(self::ERR_WRONG_KEY_TYPE); + + $this->assertInstanceOf('Predis\ServerException', $exception); + $this->assertInstanceOf('Predis\IRedisServerError', $exception); + $this->assertInstanceOf('Predis\IReplyObject', $exception); + $this->assertInstanceOf('Predis\PredisException', $exception); + } + + /** + * @group disconnected + */ + public function testErrorType() + { + $exception = new ServerException(self::ERR_WRONG_KEY_TYPE); + + $this->assertEquals('ERR', $exception->getErrorType()); + } + + /** + * @group disconnected + */ + public function testToResponseError() + { + $exception = new ServerException(self::ERR_WRONG_KEY_TYPE); + $error = $exception->toResponseError(); + + $this->assertInstanceOf('Predis\ResponseError', $error); + + $this->assertEquals($exception->getMessage(), $error->getMessage()); + $this->assertEquals($exception->getErrorType(), $error->getErrorType()); + } +} diff --git a/tests/Predis/Transaction/AbortedMultiExecExceptionTest.php b/tests/Predis/Transaction/AbortedMultiExecExceptionTest.php new file mode 100644 index 00000000..ad4f06ee --- /dev/null +++ b/tests/Predis/Transaction/AbortedMultiExecExceptionTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Transaction; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; + +/** + * + */ +class AbortedMultiExecExceptionTest extends StandardTestCase +{ + /** + * @group disconnected + */ + public function testExceptionClass() + { + $client = new Client(); + $transaction = new MultiExecContext($client); + $exception = new AbortedMultiExecException($transaction, 'ABORTED'); + + $this->assertInstanceOf('Predis\PredisException', $exception); + $this->assertSame('ABORTED', $exception->getMessage()); + $this->assertSame($transaction, $exception->getTransaction()); + } +} diff --git a/tests/Predis/Transaction/MultiExecContextTest.php b/tests/Predis/Transaction/MultiExecContextTest.php new file mode 100644 index 00000000..db34df48 --- /dev/null +++ b/tests/Predis/Transaction/MultiExecContextTest.php @@ -0,0 +1,726 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Predis\Transaction; + +use \PHPUnit_Framework_TestCase as StandardTestCase; + +use Predis\Client; +use Predis\ResponseQueued; +use Predis\ServerException; +use Predis\Commands\ICommand; + +/** + * @group realm-transaction + */ +class MultiExecContextTest extends StandardTestCase +{ + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The current profile does not support MULTI, EXEC and DISCARD + */ + public function testThrowsExceptionOnUnsupportedMultiExecInProfile() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $client = new Client($connection, '1.2'); + $tx = new MultiExecContext($client); + } + + /** + * @group disconnected + * @expectedException Predis\NotSupportedException + * @expectedExceptionMessage The current profile does not support WATCH and UNWATCH + */ + public function testThrowsExceptionOnUnsupportedWatchUnwatchInProfile() + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $client = new Client($connection, '2.0'); + $tx = new MultiExecContext($client, array('options' => 'cas')); + + $tx->watch('foo'); + } + + /** + * @group disconnected + */ + public function testExecutionWithFluentInterface() + { + $commands = array(); + $expected = array('one', 'two', 'three'); + + $callback = $this->getExecuteCallback($expected, $commands); + $tx = $this->getMockedTransaction($callback); + + $this->assertSame($expected, $tx->echo('one')->echo('two')->echo('three')->execute()); + $this->assertSame(array('MULTI', 'ECHO', 'ECHO', 'ECHO', 'EXEC'), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testExecutionWithCallable() + { + $commands = array(); + $expected = array('one', 'two', 'three'); + + $callback = $this->getExecuteCallback($expected, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->execute(function($tx) { + $tx->echo('one'); + $tx->echo('two'); + $tx->echo('three'); + }); + + $this->assertSame($expected, $replies); + $this->assertSame(array('MULTI', 'ECHO', 'ECHO', 'ECHO', 'EXEC'), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testCannotMixExecutionWithFluentInterfaceAndCallable() + { + $commands = array(); + + $callback = $this->getExecuteCallback(null, $commands); + $tx = $this->getMockedTransaction($callback); + + $exception = null; + + try { + $tx->echo('foo')->execute(function($tx) { $tx->echo('bar'); }); + } + catch (\Exception $ex) { + $exception = $ex; + } + + $this->assertInstanceOf('Predis\ClientException', $exception); + $this->assertSame(array('MULTI', 'ECHO', 'DISCARD'), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testEmptyTransactionDoesNotSendMultiExecCommands() + { + $commands = array(); + + $callback = $this->getExecuteCallback(null, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->execute(function($tx) { + // NOOP + }); + + $this->assertNull($replies); + $this->assertSame(array(), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + * @expectedException Predis\ClientException + * @expectedExceptionMessage Cannot invoke 'execute' or 'exec' inside an active client transaction block + */ + public function testThrowsExceptionOnExecInsideTransactionBlock() + { + $commands = array(); + + $callback = $this->getExecuteCallback(null, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->execute(function($tx) { + $tx->exec(); + }); + + $this->assertNull($replies); + $this->assertSame(array(), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testEmptyTransactionIgnoresDiscard() + { + $commands = array(); + + $callback = $this->getExecuteCallback(null, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->execute(function($tx) { + $tx->discard(); + }); + + $this->assertNull($replies); + $this->assertSame(array(), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testTransactionWithCommandsSendsDiscard() + { + $commands = array(); + + $callback = $this->getExecuteCallback(null, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->execute(function($tx) { + $tx->set('foo', 'bar'); + $tx->get('foo'); + $tx->discard(); + }); + + $this->assertNull($replies); + $this->assertSame(array('MULTI', 'SET', 'GET', 'DISCARD'), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testSendMultiOnCommandsFollowingDiscard() + { + $commands = array(); + $expected = array('after DISCARD'); + + $callback = $this->getExecuteCallback($expected, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->execute(function($tx) { + $tx->echo('before DISCARD'); + $tx->discard(); + $tx->echo('after DISCARD'); + }); + + $this->assertSame($replies, $expected); + $this->assertSame(array('MULTI', 'ECHO', 'DISCARD', 'MULTI', 'ECHO', 'EXEC'), self::commandsToIDs($commands)); + } + /** + * @group disconnected + * @expectedException Predis\ClientException + */ + public function testThrowsExceptionOnWatchInsideMulti() + { + $callback = $this->getExecuteCallback(); + $tx = $this->getMockedTransaction($callback); + + $tx->echo('foobar')->watch('foo')->execute(); + } + + /** + * @group disconnected + */ + public function testUnwatchInsideMulti() + { + $commands = array(); + $expected = array('foobar', true); + + $callback = $this->getExecuteCallback($expected, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->echo('foobar')->unwatch('foo')->execute(); + + $this->assertSame($replies, $expected); + $this->assertSame(array('MULTI', 'ECHO', 'UNWATCH', 'EXEC'), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testAutomaticWatchInOptions() + { + $txCommands = $casCommands = array(); + $expected = array('bar', 'piyo'); + $options = array('watch' => array('foo', 'hoge')); + + $callback = $this->getExecuteCallback($expected, $txCommands, $casCommands); + $tx = $this->getMockedTransaction($callback, $options); + + $replies = $tx->execute(function($tx) { + $tx->get('foo'); + $tx->get('hoge'); + }); + + $this->assertSame($replies, $expected); + $this->assertSame(array('WATCH'), self::commandsToIDs($casCommands)); + $this->assertSame(array('foo', 'hoge'), $casCommands[0]->getArguments()); + $this->assertSame(array('MULTI', 'GET', 'GET', 'EXEC'), self::commandsToIDs($txCommands)); + } + /** + * @group disconnected + */ + public function testCheckAndSetWithFluentInterface() + { + $txCommands = $casCommands = array(); + $expected = array('bar', 'piyo'); + $options = array('cas' => true, 'watch' => array('foo', 'hoge')); + + $callback = $this->getExecuteCallback($expected, $txCommands, $casCommands); + $tx = $this->getMockedTransaction($callback, $options); + + $tx->watch('foobar'); + $this->assertSame('DUMMY_REPLY', $tx->get('foo')); + $this->assertSame('DUMMY_REPLY', $tx->get('hoge')); + + $replies = $tx->multi() + ->get('foo') + ->get('hoge') + ->execute(); + + $this->assertSame($replies, $expected); + $this->assertSame(array('WATCH', 'WATCH', 'GET', 'GET'), self::commandsToIDs($casCommands)); + $this->assertSame(array('MULTI', 'GET', 'GET', 'EXEC'), self::commandsToIDs($txCommands)); + } + + /** + * @group disconnected + */ + public function testCheckAndSetWithBlock() + { + $txCommands = $casCommands = array(); + $expected = array('bar', 'piyo'); + $options = array('cas' => true, 'watch' => array('foo', 'hoge')); + + $callback = $this->getExecuteCallback($expected, $txCommands, $casCommands); + $tx = $this->getMockedTransaction($callback, $options); + + $test = $this; + $replies = $tx->execute(function($tx) use($test) { + $tx->watch('foobar'); + + $reply1 = $tx->get('foo'); + $reply2 = $tx->get('hoge'); + + $test->assertSame('DUMMY_REPLY', $reply1); + $test->assertSame('DUMMY_REPLY', $reply2); + + $tx->multi(); + + $tx->get('foo'); + $tx->get('hoge'); + }); + + $this->assertSame($replies, $expected); + $this->assertSame(array('WATCH', 'WATCH', 'GET', 'GET'), self::commandsToIDs($casCommands)); + $this->assertSame(array('MULTI', 'GET', 'GET', 'EXEC'), self::commandsToIDs($txCommands)); + } + + /** + * @group disconnected + */ + public function testCheckAndSetWithEmptyBlock() + { + $txCommands = $casCommands = array(); + $options = array('cas' => true); + + $callback = $this->getExecuteCallback(array(), $txCommands, $casCommands); + $tx = $this->getMockedTransaction($callback, $options); + + $tx->execute(function($tx) { + $tx->multi(); + }); + + $this->assertSame(array(), self::commandsToIDs($casCommands)); + $this->assertSame(array(), self::commandsToIDs($txCommands)); + } + + /** + * @group disconnected + */ + public function testCheckAndSetWithoutExec() + { + $txCommands = $casCommands = array(); + $options = array('cas' => true); + + $callback = $this->getExecuteCallback(array(), $txCommands, $casCommands); + $tx = $this->getMockedTransaction($callback, $options); + + $tx->execute(function($tx) { + $bar = $tx->get('foo'); + $tx->set('hoge', 'piyo'); + }); + + $this->assertSame(array('GET', 'SET'), self::commandsToIDs($casCommands)); + $this->assertSame(array(), self::commandsToIDs($txCommands)); + } + + /** + * @group disconnected + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Automatic retries can be used only when a transaction block is provided + */ + public function testThrowsExceptionOnAutomaticRetriesWithFluentInterface() + { + $options = array('retry' => 1); + + $callback = $this->getExecuteCallback(); + $tx = $this->getMockedTransaction($callback, $options); + + $tx->echo('message')->execute(); + } + + /** + * @group disconnected + */ + public function testAutomaticRetryOnServerSideTransactionAbort() + { + $casCommands = $txCommands = array(); + $expected = array('bar'); + $options = array('watch' => array('foo', 'bar'), 'retry' => ($attempts = 2) + 1); + + $sentinel = $this->getMock('stdClass', array('signal')); + $sentinel->expects($this->exactly($attempts))->method('signal'); + + $callback = $this->getExecuteCallback($expected, $txCommands, $casCommands); + $tx = $this->getMockedTransaction($callback, $options); + + $replies = $tx->execute(function($tx) use($sentinel, &$attempts) { + $tx->get('foo'); + if ($attempts > 0) { + $attempts -= 1; + $sentinel->signal(); + $tx->echo('!!ABORT!!'); + } + }); + + $this->assertSame($replies, $expected); + $this->assertSame(array('WATCH'), self::commandsToIDs($casCommands)); + $this->assertSame(array('foo', 'bar'), $casCommands[0]->getArguments()); + $this->assertSame(array('MULTI', 'GET', 'EXEC'), self::commandsToIDs($txCommands)); + } + + /** + * @group disconnected + * @expectedException Predis\Transaction\AbortedMultiExecException + */ + public function testThrowsExceptionOnServerSideTransactionAbort() + { + $callback = $this->getExecuteCallback(); + $tx = $this->getMockedTransaction($callback); + + $replies = $tx->execute(function($tx) { + $tx->echo('!!ABORT!!'); + }); + } + + /** + * @group disconnected + */ + public function testHandlesStandardExceptionsInBlock() + { + $commands = array(); + $expected = array('foobar', true); + + $callback = $this->getExecuteCallback($expected, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = null; + + try { + $replies = $tx->execute(function($tx) { + $tx->set('foo', 'bar'); + $tx->get('foo'); + throw new \RuntimeException('TEST'); + }); + } + catch (\Exception $ex) { + // NOOP + } + + $this->assertNull($replies, $expected); + $this->assertSame(array('MULTI', 'SET', 'GET', 'DISCARD'), self::commandsToIDs($commands)); + } + + /** + * @group disconnected + */ + public function testHandlesServerExceptionsInBlock() + { + $commands = array(); + $expected = array('foobar', true); + + $callback = $this->getExecuteCallback($expected, $commands); + $tx = $this->getMockedTransaction($callback); + + $replies = null; + + try { + $replies = $tx->execute(function($tx) { + $tx->set('foo', 'bar'); + $tx->echo('ERR Invalid operation'); + $tx->get('foo'); + }); + } + catch (ServerException $ex) { + $tx->discard(); + } + + $this->assertNull($replies); + $this->assertSame(array('MULTI', 'SET', 'ECHO', 'DISCARD'), self::commandsToIDs($commands)); + } + + // ******************************************************************** // + // ---- INTEGRATION TESTS --------------------------------------------- // + // ******************************************************************** // + + /** + * @group connected + */ + public function testIntegrationHandlesStandardExceptionsInBlock() + { + $client = $this->getClient(); + $exception = null; + + try { + $client->multiExec(function($tx) { + $tx->set('foo', 'bar'); + throw new \RuntimeException("TEST"); + }); + } + catch (\Exception $ex) { + $exception = $ex; + } + + $this->assertInstanceOf('RuntimeException', $exception); + $this->assertFalse($client->exists('foo')); + } + + /** + * @group connected + */ + public function testIntegrationSendMultiOnCommandsAfterDiscard() + { + $client = $this->getClient(); + + $replies = $client->multiExec(function($tx) { + $tx->set('foo', 'bar'); + $tx->discard(); + $tx->set('hoge', 'piyo'); + }); + + $this->assertSame(1, count($replies)); + $this->assertFalse($client->exists('foo')); + $this->assertTrue($client->exists('hoge')); + } + + /** + * @group connected + */ + public function testIntegrationWritesOnWatchedKeysAbortTransaction() + { + $exception = null; + $client1 = $this->getClient(); + $client2 = $this->getClient(); + + try { + $client1->multiExec(array('watch' => 'sentinel'), function($tx) use($client2) { + $tx->set('sentinel', 'client1'); + $tx->get('sentinel'); + $client2->set('sentinel', 'client2'); + }); + } + catch (AbortedMultiExecException $ex) { + $exception = $ex; + } + + $this->assertInstanceOf('Predis\Transaction\AbortedMultiExecException', $exception); + $this->assertSame('client2', $client1->get('sentinel')); + } + + /** + * @group connected + */ + public function testIntegrationCheckAndSetWithDiscardAndRetry() + { + $client = $this->getClient(); + + $client->set('foo', 'bar'); + $options = array('watch' => 'foo', 'cas' => true); + + $replies = $client->multiExec($options, function($tx) { + $tx->watch('foobar'); + $foo = $tx->get('foo'); + $tx->multi(); + $tx->set('foobar', $foo); + $tx->discard(); + $tx->mget('foo', 'foobar'); + }); + + $this->assertInternalType('array', $replies); + $this->assertSame(array(array('bar', null)), $replies); + + $hijack = true; + $client2 = $this->getClient(); + $client->set('foo', 'bar'); + + $options = array('watch' => 'foo', 'cas' => true, 'retry' => 1); + $replies = $client->multiExec($options, function($tx) use($client2, &$hijack) { + $foo = $tx->get('foo'); + $tx->multi(); + $tx->set('foobar', $foo); + $tx->discard(); + if ($hijack) { + $hijack = false; + $client2->set('foo', 'hijacked!'); + } + $tx->mget('foo', 'foobar'); + }); + + $this->assertInternalType('array', $replies); + $this->assertSame(array(array('hijacked!', null)), $replies); + } + + // ******************************************************************** // + // ---- HELPER METHODS ------------------------------------------------ // + // ******************************************************************** // + + /** + * Returns a mocked instance of Predis\Network\IConnectionSingle using + * the specified callback to return values from the executeCommand method. + * + * @param \Closure $executeCallback + * @return \Predis\Network\IConnectionSingle + */ + protected function getMockedConnection($executeCallback) + { + $connection = $this->getMock('Predis\Network\IConnectionSingle'); + $connection->expects($this->any()) + ->method('executeCommand') + ->will($this->returnCallback($executeCallback)); + + return $connection; + } + + /** + * Returns a mocked instance of Predis\Transaction\MultiExecContext using + * the specified callback to return values from the executeCommand method + * of the underlying connection. + * + * @param \Closure $executeCallback + * @return MultiExecContext + */ + protected function getMockedTransaction($executeCallback, $options = array()) + { + $connection = $this->getMockedConnection($executeCallback); + $client = new Client($connection); + $transaction = new MultiExecContext($client, $options); + + return $transaction; + } + + /** + * Returns a callback that emulates a server-side MULTI/EXEC transaction context. + * + * @param array $expected Expected replies. + * @param array $commands Reference to an array that stores the whole flow of commands. + * @return \Closure + */ + protected function getExecuteCallback($expected = array(), &$commands = array(), &$cas = array()) + { + $multi = $watch = $abort = false; + + return function(ICommand $command) use(&$expected, &$commands, &$cas, &$multi, &$watch, &$abort) { + $cmd = $command->getId(); + + if ($multi || $cmd === 'MULTI') { + $commands[] = $command; + } + else { + $cas[] = $command; + } + + switch ($cmd) { + case 'WATCH': + if ($multi) { + throw new ServerException("ERR $cmd inside MULTI is not allowed"); + } + return $watch = true; + + case 'MULTI': + if ($multi) { + throw new ServerException("ERR MULTI calls can not be nested"); + } + return $multi = true; + + case 'EXEC': + if (!$multi) { + throw new ServerException("ERR $cmd without MULTI"); + } + $watch = $multi = false; + if ($abort) { + $commands = $cas = array(); + $abort = false; + return null; + } + return $expected; + + case 'DISCARD': + if (!$multi) { + throw new ServerException("ERR $cmd without MULTI"); + } + $watch = $multi = false; + return true; + + case 'ECHO': + @list($trigger) = $command->getArguments(); + if (strpos($trigger, 'ERR ') === 0) { + throw new ServerException($trigger); + } + if ($trigger === '!!ABORT!!' && $multi) { + $abort = true; + } + return new ResponseQueued(); + + case 'UNWATCH': + $watch = false; + + default: + return $multi ? new ResponseQueued() : 'DUMMY_REPLY'; + } + }; + } + + /** + * Converts an array of instances of Predis\Commands\ICommand and + * returns an array containing their IDs. + * + * @param array $commands List of commands instances. + * @return array + */ + protected static function commandsToIDs($commands) { + return array_map(function($cmd) { return $cmd->getId(); }, $commands); + } + + /** + * Returns a client instance connected to the specified Redis + * server instance to perform integration tests. + * + * @return array Additional connection parameters. + * @return Client client instance. + */ + protected function getClient(Array $parameters = array()) + { + $parameters = array_merge(array( + 'scheme' => 'tcp', + 'host' => REDIS_SERVER_HOST, + 'port' => REDIS_SERVER_PORT, + 'database' => REDIS_SERVER_DBNUM, + ), $parameters); + + $client = new Client($parameters, array('profile' => REDIS_SERVER_VERSION)); + + $client->connect(); + $client->flushdb(); + + return $client; + } +} diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..269a2b9b --- /dev/null +++ b/tests/README.md @@ -0,0 +1,88 @@ +# About testing Predis # + +__ATTENTION__: Do not run this test suite against instances of Redis running in +production environments or containing data you are interested in! If you still +want to test this software on a production server without hitting the database, +please read on to undestand how to disable integration tests. + +Predis ships with a comprehensive test suite that uses __PHPUnit__ to cover every +aspect of the library. The suite is organized into several unit groups with the +PHPUnit `@group` annotation which makes it possible to run only selected groups +of tests. The main groups are: + + - __disconnected__: generic tests that verify the correct behaviour of the + library without requiring an active connection to Redis. + - __connected__: integration tests that require an active connection to Redis + - __commands__: tests for the implementation of Redis commands. + - __slow__: tests that might slow down the execution of the test suite, they + can be either __connected__ or __disconnected__. + +A list of all the available groups in the suite can be obtained by running: + +```bash +$ phpunit --list-groups +``` +Groups of tests can be disabled or enabled via the XML configuration file or the +standard command-line test runner. Please note that due to a bug in PHPUnit, +older versions ignore the `--group` option when the group is excluded in the XML +configuration file. More details about this issue are available on [PHPUnit's bug +tracker](http://github.com/sebastianbergmann/phpunit/issues/320). + +Certain groups of tests that require native extensions, such as `ext-curl` or +`ext-phpiredis`, are excluded by default in the XML configuration file. If you want +to test Predis using the phpiredis-based connection or against an instance of Webdis, +you should remove those groups of tests from the exclusion list in `phpunit.xml`. + +### Combining groups for inclusion or exclusion with the command-line runner ### + +```bash +$ phpunit --group disconnected --exclude-group commands,slow +``` + +### Integration tests ### + +The suite performs integration tests against a running instance of Redis (>= 2.4.0 +is required) to verify the correct behaviour of the implementation of each command +and certain abstractions implemented in Predis that depend on them. These tests are +identified by the __connected__ group. + +Integration tests for commands that are not defined in the specified server profile +(see the value of the `TEST_SERVER_VERSION` constant in `phpunit.xml`) are marked +as __skipped__ automatically. + +By default, the test suite is configured to execute integration tests using the +server profile for Redis v2.4 (which is the current stable version of Redis). You +can optionally run the suite against a Redis instance built from the `unstable` +branch with the development profile by changing the `TEST_SERVER_VERSION` to `dev` +in the `phpunit.xml` file. + +If you do not have a Redis instance up and running or available for testing, you +can disable integration tests completely by excluding the __connected__ group: + +```bash +$ phpunit --exclude-group connected +``` + +### Slow tests ### + +Certain tests can slow down the execution of the test suite. These tests can be disabled +by excluding the by the __slow__ group: + +```bash +$ phpunit --exclude-group slow +``` + +### Testing Redis commands ### + +We also provide an helper script in the `bin` directory that can be used to automatically +generate a file with the scheleton of a test case to test a Redis command by specifying +the name of the class in the `Predis\Commands` namespace (only classes in this namespace +are considered valid). For example, to generate a test case for `SET` (represented by the +`Predis\Commands\StringSet` class): + +```bash +$ ./bin/generate-command-test.php --class=StringSet +``` +Each command has its own realm (commands that operate on strings, lists, sets and such) +and this realm is automatically inferred from the name of the specified class. The realm +can be also specified manually using the `--realm` option. diff --git a/test/bootstrap.php b/tests/bootstrap.php similarity index 50% rename from test/bootstrap.php rename to tests/bootstrap.php index 3566dd55..43c600ea 100644 --- a/test/bootstrap.php +++ b/tests/bootstrap.php @@ -10,4 +10,9 @@ */ require __DIR__.'/../autoload.php'; -require __DIR__.'/PredisShared.php'; + +require __DIR__.'/PHPUnit/ArrayHasSameValuesConstraint.php'; +require __DIR__.'/PHPUnit/CommandTestCase.php'; +require __DIR__.'/PHPUnit/ConnectionTestCase.php'; +require __DIR__.'/PHPUnit/ServerVersionTestCase.php'; +require __DIR__.'/PHPUnit/DistributionStrategyTestCase.php';