PredisConnectionTestCase.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <?php
  2. /*
  3. * This file is part of the Predis package.
  4. *
  5. * (c) Daniele Alessandri <suppakilla@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Predis\Connection;
  11. use Predis\Profile;
  12. use PredisTestCase;
  13. /**
  14. * @group realm-connection
  15. */
  16. abstract class PredisConnectionTestCase extends PredisTestCase
  17. {
  18. /**
  19. * @group disconnected
  20. * @group slow
  21. * @expectedException \Predis\Connection\ConnectionException
  22. */
  23. public function testThrowExceptionWhenUnableToConnect()
  24. {
  25. $parameters = array('host' => '169.254.10.10', 'timeout' => 0.5);
  26. $connection = $this->getConnection($profile, false, $parameters);
  27. $connection->executeCommand($this->getProfile()->createCommand('ping'));
  28. }
  29. // ******************************************************************** //
  30. // ---- INTEGRATION TESTS --------------------------------------------- //
  31. // ******************************************************************** //
  32. /**
  33. * @group connected
  34. */
  35. public function testConnectForcesConnection()
  36. {
  37. $connection = $this->getConnection();
  38. $this->assertFalse($connection->isConnected());
  39. $connection->connect();
  40. $this->assertTrue($connection->isConnected());
  41. }
  42. /**
  43. * @group connected
  44. */
  45. public function testDoesNotThrowExceptionOnConnectWhenAlreadyConnected()
  46. {
  47. $connection = $this->getConnection();
  48. $connection->connect();
  49. $this->assertTrue($connection->isConnected());
  50. $connection->connect();
  51. $this->assertTrue($connection->isConnected());
  52. }
  53. /**
  54. * @group connected
  55. */
  56. public function testDisconnectForcesDisconnection()
  57. {
  58. $connection = $this->getConnection();
  59. $connection->connect();
  60. $this->assertTrue($connection->isConnected());
  61. $connection->disconnect();
  62. $this->assertFalse($connection->isConnected());
  63. }
  64. /**
  65. * @group disconnected
  66. */
  67. public function testDoesNotThrowExceptionOnDisconnectWhenAlreadyDisconnected()
  68. {
  69. $connection = $this->getConnection();
  70. $this->assertFalse($connection->isConnected());
  71. $connection->disconnect();
  72. $this->assertFalse($connection->isConnected());
  73. }
  74. /**
  75. * @group connected
  76. */
  77. public function testGetResourceForcesConnection()
  78. {
  79. $connection = $this->getConnection();
  80. $this->assertFalse($connection->isConnected());
  81. $this->assertInternalType('resource', $connection->getResource());
  82. $this->assertTrue($connection->isConnected());
  83. }
  84. /**
  85. * @group connected
  86. */
  87. public function testSendingCommandForcesConnection()
  88. {
  89. $connection = $this->getConnection($profile);
  90. $cmdPing = $profile->createCommand('ping');
  91. $this->assertEquals('PONG', $connection->executeCommand($cmdPing));
  92. $this->assertTrue($connection->isConnected());
  93. }
  94. /**
  95. * @group connected
  96. */
  97. public function testExecutesCommandOnServer()
  98. {
  99. $profile = $this->getProfile();
  100. $connection = $this->getConnection($profile);
  101. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse'));
  102. $cmdPing->expects($this->never())
  103. ->method('parseResponse');
  104. $this->assertEquals('PONG', $connection->executeCommand($cmdPing));
  105. }
  106. /**
  107. * @group connected
  108. */
  109. public function testExecutesMultipleCommandsOnServer()
  110. {
  111. $connection = $this->getConnection($profile, true);
  112. $cmdPing = $profile->createCommand('ping');
  113. $cmdEcho = $profile->createCommand('echo', array('echoed'));
  114. $cmdGet = $profile->createCommand('get', array('foobar'));
  115. $cmdRpush = $profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol'));
  116. $cmdLrange = $profile->createCommand('lrange', array('metavars', 0, -1));
  117. $this->assertEquals('PONG', $connection->executeCommand($cmdPing));
  118. $this->assertSame('echoed', $connection->executeCommand($cmdEcho));
  119. $this->assertNull($connection->executeCommand($cmdGet));
  120. $this->assertSame(3, $connection->executeCommand($cmdRpush));
  121. $this->assertSame(array('foo', 'hoge', 'lol'), $connection->executeCommand($cmdLrange));
  122. }
  123. /**
  124. * @group connected
  125. */
  126. public function testWritesCommandToServer()
  127. {
  128. $profile = $this->getProfile();
  129. $connection = $this->getConnection($profile);
  130. $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('parseResponse'));
  131. $cmdEcho->setArguments(array('ECHOED'));
  132. $cmdEcho->expects($this->never())
  133. ->method('parseResponse');
  134. $connection->writeRequest($cmdEcho);
  135. $connection->disconnect();
  136. }
  137. /**
  138. * @group connected
  139. */
  140. public function testReadsCommandFromServer()
  141. {
  142. $profile = $this->getProfile();
  143. $connection = $this->getConnection($profile);
  144. $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('parseResponse'));
  145. $cmdEcho->setArguments(array('ECHOED'));
  146. $cmdEcho->expects($this->never())
  147. ->method('parseResponse');
  148. $connection->writeRequest($cmdEcho);
  149. $this->assertSame('ECHOED', $connection->readResponse($cmdEcho));
  150. }
  151. /**
  152. * @group connected
  153. */
  154. public function testIsAbleToWriteMultipleCommandsAndReadThemBackForPipelining()
  155. {
  156. $profile = $this->getProfile();
  157. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse'));
  158. $cmdPing->expects($this->never())
  159. ->method('parseResponse');
  160. $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('parseResponse'));
  161. $cmdEcho->setArguments(array('ECHOED'));
  162. $cmdEcho->expects($this->never())
  163. ->method('parseResponse');
  164. $connection = $this->getConnection();
  165. $connection->writeRequest($cmdPing);
  166. $connection->writeRequest($cmdEcho);
  167. $this->assertEquals('PONG', $connection->readResponse($cmdPing));
  168. $this->assertSame('ECHOED', $connection->readResponse($cmdEcho));
  169. }
  170. /**
  171. * @group connected
  172. */
  173. public function testSendsInitializationCommandsOnConnection()
  174. {
  175. $profile = $this->getProfile();
  176. $connection = $this->getConnection($profile, true);
  177. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('getArguments'));
  178. $cmdPing->expects($this->once())
  179. ->method('getArguments')
  180. ->will($this->returnValue(array()));
  181. $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('getArguments'));
  182. $cmdEcho->expects($this->once())
  183. ->method('getArguments')
  184. ->will($this->returnValue(array('ECHOED')));
  185. $connection->addConnectCommand($cmdPing);
  186. $connection->addConnectCommand($cmdEcho);
  187. $connection->connect();
  188. }
  189. /**
  190. * @group connected
  191. */
  192. public function testReadsStatusResponses()
  193. {
  194. $profile = $this->getProfile();
  195. $connection = $this->getConnection($profile, true);
  196. $connection->writeRequest($profile->createCommand('set', array('foo', 'bar')));
  197. $this->assertInstanceOf('Predis\Response\Status', $connection->read());
  198. $connection->writeRequest($profile->createCommand('ping'));
  199. $this->assertInstanceOf('Predis\Response\Status', $connection->read());
  200. $connection->writeRequest($profile->createCommand('multi'));
  201. $connection->writeRequest($profile->createCommand('ping'));
  202. $this->assertInstanceOf('Predis\Response\Status', $connection->read());
  203. $this->assertInstanceOf('Predis\Response\Status', $connection->read());
  204. }
  205. /**
  206. * @group connected
  207. */
  208. public function testReadsBulkResponses()
  209. {
  210. $profile = $this->getProfile();
  211. $connection = $this->getConnection($profile, true);
  212. $connection->executeCommand($profile->createCommand('set', array('foo', 'bar')));
  213. $connection->writeRequest($profile->createCommand('get', array('foo')));
  214. $this->assertSame('bar', $connection->read());
  215. $connection->writeRequest($profile->createCommand('get', array('hoge')));
  216. $this->assertNull($connection->read());
  217. }
  218. /**
  219. * @group connected
  220. */
  221. public function testReadsIntegerResponses()
  222. {
  223. $profile = $this->getProfile();
  224. $connection = $this->getConnection($profile, true);
  225. $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')));
  226. $connection->writeRequest($profile->createCommand('llen', array('metavars')));
  227. $this->assertSame(3, $connection->read());
  228. }
  229. /**
  230. * @group connected
  231. */
  232. public function testReadsErrorResponsesAsResponseErrorObjects()
  233. {
  234. $profile = $this->getProfile();
  235. $connection = $this->getConnection($profile, true);
  236. $connection->executeCommand($profile->createCommand('set', array('foo', 'bar')));
  237. $connection->writeRequest($profile->createCommand('rpush', array('foo', 'baz')));
  238. $this->assertInstanceOf('Predis\Response\Error', $error = $connection->read());
  239. $this->assertRegExp('/[ERR|WRONGTYPE] Operation against a key holding the wrong kind of value/', $error->getMessage());
  240. }
  241. /**
  242. * @group connected
  243. */
  244. public function testReadsMultibulkResponsesAsArrays()
  245. {
  246. $profile = $this->getProfile();
  247. $connection = $this->getConnection($profile, true);
  248. $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')));
  249. $connection->writeRequest($profile->createCommand('lrange', array('metavars', 0, -1)));
  250. $this->assertSame(array('foo', 'hoge', 'lol'), $connection->read());
  251. }
  252. /**
  253. * @group connected
  254. * @group slow
  255. * @expectedException \Predis\Connection\ConnectionException
  256. */
  257. public function testThrowsExceptionOnConnectionTimeout()
  258. {
  259. $connection = $this->getConnection($_, false, array('host' => '169.254.10.10', 'timeout' => 0.5));
  260. $connection->connect();
  261. }
  262. /**
  263. * @group connected
  264. * @group slow
  265. * @expectedException \Predis\Connection\ConnectionException
  266. */
  267. public function testThrowsExceptionOnReadWriteTimeout()
  268. {
  269. $profile = $this->getProfile();
  270. $connection = $this->getConnection($profile, true, array('read_write_timeout' => 0.5));
  271. $connection->executeCommand($profile->createCommand('brpop', array('foo', 3)));
  272. }
  273. // ******************************************************************** //
  274. // ---- HELPER METHODS ------------------------------------------------ //
  275. // ******************************************************************** //
  276. /**
  277. * Returns a named array with the default connection parameters and their values.
  278. *
  279. * @return array Default connection parameters.
  280. */
  281. protected function getDefaultParametersArray()
  282. {
  283. return array(
  284. 'scheme' => 'tcp',
  285. 'host' => REDIS_SERVER_HOST,
  286. 'port' => REDIS_SERVER_PORT,
  287. 'database' => REDIS_SERVER_DBNUM,
  288. 'read_write_timeout' => 2,
  289. );
  290. }
  291. /**
  292. * Asserts that the connection is using a persistent resource stream.
  293. *
  294. * This assertion will trigger a connect() operation if the connection has
  295. * not been open yet.
  296. *
  297. * @param NodeConnectionInterface $connection Connection instance.
  298. */
  299. protected function assertPersistentConnection(NodeConnectionInterface $connection)
  300. {
  301. $this->assertSame('persistent stream', get_resource_type($connection->getResource()));
  302. }
  303. /**
  304. * Asserts that the connection is not using a persistent resource stream.
  305. *
  306. * This assertion will trigger a connect() operation if the connection has
  307. * not been open yet.
  308. *
  309. * @param NodeConnectionInterface $connection Connection instance.
  310. */
  311. protected function assertNonPersistentConnection(NodeConnectionInterface $connection)
  312. {
  313. $this->assertSame('stream', get_resource_type($connection->getResource()));
  314. }
  315. /**
  316. * Returns a new instance of a connection instance.
  317. *
  318. * @param Profile\ProfileInterface $profile Reference to the server profile instance.
  319. * @param bool $initialize Push default initialization commands (SELECT and FLUSHDB).
  320. * @param array $parameters Additional connection parameters.
  321. *
  322. * @return StreamConnection
  323. */
  324. protected function getConnection(&$profile = null, $initialize = false, array $parameters = array())
  325. {
  326. $class = static::CONNECTION_CLASS;
  327. $parameters = $this->getParameters($parameters);
  328. $profile = $this->getProfile();
  329. $connection = new $class($parameters);
  330. if ($initialize) {
  331. $connection->addConnectCommand(
  332. $profile->createCommand('select', array($parameters->database))
  333. );
  334. $connection->addConnectCommand(
  335. $profile->createCommand('flushdb')
  336. );
  337. }
  338. return $connection;
  339. }
  340. }