ConnectionTestCase.php 11 KB

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