ConnectionTestCase.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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 \PHPUnit_Framework_TestCase as StandardTestCase;
  12. use Predis\Profile\ServerProfile;
  13. /**
  14. * @group realm-connection
  15. */
  16. abstract class ConnectionTestCase extends StandardTestCase
  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. * @expectedException Predis\ClientException
  45. * @expectedExceptionMessage Connection already estabilished
  46. */
  47. public function testThrowsExceptionOnConnectWhenAlreadyConnected()
  48. {
  49. $connection = $this->getConnection();
  50. $connection->connect();
  51. $connection->connect();
  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->assertSame('PONG', $connection->executeCommand($cmdPing));
  92. $this->assertTrue($connection->isConnected());
  93. }
  94. /**
  95. * @group connected
  96. */
  97. public function testExecutesCommandOnServer()
  98. {
  99. $connection = $this->getConnection($profile);
  100. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse'));
  101. $cmdPing->expects($this->never())
  102. ->method('parseResponse');
  103. $this->assertSame('PONG', $connection->executeCommand($cmdPing));
  104. }
  105. /**
  106. * @group connected
  107. */
  108. public function testWritesCommandToServer()
  109. {
  110. $connection = $this->getConnection($profile);
  111. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse'));
  112. $cmdPing->expects($this->never())
  113. ->method('parseResponse');
  114. $connection->writeCommand($cmdPing);
  115. $connection->disconnect();
  116. }
  117. /**
  118. * @group connected
  119. */
  120. public function testReadsCommandFromServer()
  121. {
  122. $connection = $this->getConnection($profile);
  123. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse'));
  124. $cmdPing->expects($this->never())
  125. ->method('parseResponse');
  126. $connection->writeCommand($cmdPing);
  127. $this->assertSame('PONG', $connection->readResponse($cmdPing));
  128. }
  129. /**
  130. * @group connected
  131. */
  132. public function testIsAbleToWriteMultipleCommandsAndReadThemBackForPipelining()
  133. {
  134. $connection = $this->getConnection($profile);
  135. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('parseResponse'));
  136. $cmdPing->expects($this->never())
  137. ->method('parseResponse');
  138. $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('parseResponse'));
  139. $cmdEcho->setArguments(array('ECHOED'));
  140. $cmdEcho->expects($this->never())
  141. ->method('parseResponse');
  142. $connection = $this->getConnection();
  143. $connection->writeCommand($cmdPing);
  144. $connection->writeCommand($cmdEcho);
  145. $this->assertSame('PONG', $connection->readResponse($cmdPing));
  146. $this->assertSame('ECHOED', $connection->readResponse($cmdEcho));
  147. }
  148. /**
  149. * @group connected
  150. */
  151. public function testSendsInitializationCommandsOnConnection()
  152. {
  153. $connection = $this->getConnection($profile, true);
  154. $cmdPing = $this->getMock($profile->getCommandClass('ping'), array('getArguments'));
  155. $cmdPing->expects($this->once())
  156. ->method('getArguments')
  157. ->will($this->returnValue(array()));
  158. $cmdEcho = $this->getMock($profile->getCommandClass('echo'), array('getArguments'));
  159. $cmdEcho->expects($this->once())
  160. ->method('getArguments')
  161. ->will($this->returnValue(array('ECHOED')));
  162. $connection->pushInitCommand($cmdPing);
  163. $connection->pushInitCommand($cmdEcho);
  164. $connection->connect();
  165. }
  166. /**
  167. * @group connected
  168. */
  169. public function testReadsStatusReplies()
  170. {
  171. $connection = $this->getConnection($profile, true);
  172. $connection->writeCommand($profile->createCommand('set', array('foo', 'bar')));
  173. $this->assertTrue($connection->read());
  174. $connection->writeCommand($profile->createCommand('ping'));
  175. $this->assertSame('PONG', $connection->read());
  176. $connection->writeCommand($profile->createCommand('multi'));
  177. $connection->writeCommand($profile->createCommand('ping'));
  178. $this->assertTrue($connection->read());
  179. $this->assertInstanceOf('Predis\ResponseQueued', $connection->read());
  180. }
  181. /**
  182. * @group connected
  183. */
  184. public function testReadsBulkReplies()
  185. {
  186. $connection = $this->getConnection($profile, true);
  187. $connection->executeCommand($profile->createCommand('set', array('foo', 'bar')));
  188. $connection->writeCommand($profile->createCommand('get', array('foo')));
  189. $this->assertSame('bar', $connection->read());
  190. $connection->writeCommand($profile->createCommand('get', array('hoge')));
  191. $this->assertNull($connection->read());
  192. }
  193. /**
  194. * @group connected
  195. */
  196. public function testReadsIntegerReplies()
  197. {
  198. $connection = $this->getConnection($profile, true);
  199. $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')));
  200. $connection->writeCommand($profile->createCommand('llen', array('metavars')));
  201. $this->assertSame(3, $connection->read());
  202. }
  203. /**
  204. * @group connected
  205. */
  206. public function testReadsErrorRepliesAsResponseErrorObjects()
  207. {
  208. $connection = $this->getConnection($profile, true);
  209. $connection->executeCommand($profile->createCommand('set', array('foo', 'bar')));
  210. $connection->writeCommand($profile->createCommand('rpush', array('foo', 'baz')));
  211. $this->assertInstanceOf('Predis\ResponseError', $error = $connection->read());
  212. $this->assertRegExp('/[ERR|WRONGTYPE] Operation against a key holding the wrong kind of value/', $error->getMessage());
  213. }
  214. /**
  215. * @group connected
  216. */
  217. public function testReadsMultibulkRepliesAsArrays()
  218. {
  219. $connection = $this->getConnection($profile, true);
  220. $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')));
  221. $connection->writeCommand($profile->createCommand('lrange', array('metavars', 0, -1)));
  222. $this->assertSame(array('foo', 'hoge', 'lol'), $connection->read());
  223. }
  224. /**
  225. * @group connected
  226. * @group slow
  227. * @expectedException Predis\Connection\ConnectionException
  228. * @expectedExceptionMessage Connection timed out
  229. */
  230. public function testThrowsExceptionOnConnectionTimeout()
  231. {
  232. $connection = $this->getConnection($_, false, array('host' => '169.254.10.10', 'timeout' => 0.5));
  233. $connection->connect();
  234. }
  235. /**
  236. * @group connected
  237. * @group slow
  238. * @expectedException Predis\Connection\ConnectionException
  239. */
  240. public function testThrowsExceptionOnReadWriteTimeout()
  241. {
  242. $connection = $this->getConnection($profile, true, array('read_write_timeout' => 0.5));
  243. $connection->executeCommand($profile->createCommand('brpop', array('foo', 3)));
  244. }
  245. // ******************************************************************** //
  246. // ---- HELPER METHODS ------------------------------------------------ //
  247. // ******************************************************************** //
  248. /**
  249. * Returns a named array with the default connection parameters and their values.
  250. *
  251. * @return Array Default connection parameters.
  252. */
  253. protected function getDefaultParametersArray()
  254. {
  255. return array(
  256. 'scheme' => 'tcp',
  257. 'host' => REDIS_SERVER_HOST,
  258. 'port' => REDIS_SERVER_PORT,
  259. 'database' => REDIS_SERVER_DBNUM,
  260. 'read_write_timeout' => 2,
  261. );
  262. }
  263. /**
  264. * Returns a new instance of connection parameters.
  265. *
  266. * @param array $additional Additional connection parameters.
  267. * @return ConnectionParameters Default connection parameters.
  268. */
  269. protected function getParameters($additional = array())
  270. {
  271. $parameters = array_merge($this->getDefaultParametersArray(), $additional);
  272. $parameters = new ConnectionParameters($parameters);
  273. return $parameters;
  274. }
  275. /**
  276. * Returns a new instance of server profile.
  277. *
  278. * @param array $additional Additional connection parameters.
  279. * @return ServerProfile
  280. */
  281. protected function getProfile($version = null)
  282. {
  283. return ServerProfile::get($version ?: REDIS_SERVER_VERSION);
  284. }
  285. /**
  286. * Returns a new instance of a connection instance.
  287. *
  288. * @param ServerProfile $profile Reference to the server profile instance.
  289. * @param Boolean $initialize Push default initialization commands (SELECT and FLUSHDB).
  290. * @param array $parameters Additional connection parameters.
  291. * @return StreamConnection
  292. */
  293. protected abstract function getConnection(&$profile = null, $initialize = false, Array $parameters = array());
  294. }