HashRingTest.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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\Cluster\Distributor;
  11. /**
  12. *
  13. */
  14. class HashRingTest extends PredisDistributorTestCase
  15. {
  16. /**
  17. * {@inheritdoc}
  18. */
  19. public function getDistributorInstance()
  20. {
  21. return new HashRing();
  22. }
  23. /**
  24. * @group disconnected
  25. */
  26. public function testHash()
  27. {
  28. $ring = $this->getDistributorInstance();
  29. $this->assertEquals(crc32('foobar'), $ring->hash('foobar'));
  30. }
  31. /**
  32. * @group disconnected
  33. */
  34. public function testSingleNodeInRing()
  35. {
  36. $node = '127.0.0.1:7000';
  37. $ring = $this->getDistributorInstance();
  38. $ring->add($node);
  39. $expected = array_fill(0, 20, $node);
  40. $actual = $this->getNodes($ring, 20);
  41. $this->assertSame($expected, $actual);
  42. }
  43. /**
  44. * @group disconnected
  45. */
  46. public function testMultipleNodesInRing()
  47. {
  48. $ring = $this->getSampleDistribution(array(
  49. '127.0.0.1:7000',
  50. '127.0.0.1:7001',
  51. '127.0.0.1:7002',
  52. ));
  53. $expected = array(
  54. '127.0.0.1:7001',
  55. '127.0.0.1:7001',
  56. '127.0.0.1:7001',
  57. '127.0.0.1:7002',
  58. '127.0.0.1:7002',
  59. '127.0.0.1:7001',
  60. '127.0.0.1:7001',
  61. '127.0.0.1:7000',
  62. '127.0.0.1:7001',
  63. '127.0.0.1:7002',
  64. '127.0.0.1:7002',
  65. '127.0.0.1:7002',
  66. '127.0.0.1:7002',
  67. '127.0.0.1:7000',
  68. '127.0.0.1:7002',
  69. '127.0.0.1:7002',
  70. '127.0.0.1:7002',
  71. '127.0.0.1:7000',
  72. '127.0.0.1:7001',
  73. '127.0.0.1:7002',
  74. );
  75. $actual = $this->getNodes($ring, 20);
  76. $this->assertSame($expected, $actual);
  77. }
  78. /**
  79. * @group disconnected
  80. */
  81. public function testSubsequendAddAndRemoveFromRing()
  82. {
  83. $ring = $this->getDistributorInstance();
  84. $expected1 = array_fill(0, 10, '127.0.0.1:7000');
  85. $expected3 = array_fill(0, 10, '127.0.0.1:7001');
  86. $expected2 = array(
  87. '127.0.0.1:7001',
  88. '127.0.0.1:7001',
  89. '127.0.0.1:7001',
  90. '127.0.0.1:7001',
  91. '127.0.0.1:7001',
  92. '127.0.0.1:7001',
  93. '127.0.0.1:7001',
  94. '127.0.0.1:7000',
  95. '127.0.0.1:7001',
  96. '127.0.0.1:7000',
  97. );
  98. $ring->add('127.0.0.1:7000');
  99. $actual1 = $this->getNodes($ring, 10);
  100. $ring->add('127.0.0.1:7001');
  101. $actual2 = $this->getNodes($ring, 10);
  102. $ring->remove('127.0.0.1:7000');
  103. $actual3 = $this->getNodes($ring, 10);
  104. $this->assertSame($expected1, $actual1);
  105. $this->assertSame($expected2, $actual2);
  106. $this->assertSame($expected3, $actual3);
  107. }
  108. /**
  109. * @group disconnected
  110. */
  111. public function testGetByValue()
  112. {
  113. $ring = $this->getSampleDistribution(array(
  114. '127.0.0.1:7000',
  115. '127.0.0.1:7001',
  116. '127.0.0.1:7002',
  117. ));
  118. $this->assertSame('127.0.0.1:7001', $ring->get('uid:256'));
  119. $this->assertSame('127.0.0.1:7001', $ring->get('uid:281'));
  120. $this->assertSame('127.0.0.1:7000', $ring->get('uid:312'));
  121. $this->assertSame('127.0.0.1:7001', $ring->get('uid:432'));
  122. $this->assertSame('127.0.0.1:7002', $ring->get('uid:500'));
  123. $this->assertSame('127.0.0.1:7000', $ring->get('uid:641'));
  124. }
  125. /**
  126. * @group disconnected
  127. */
  128. public function testGetByHash()
  129. {
  130. $ring = $this->getSampleDistribution(array(
  131. '127.0.0.1:7000',
  132. '127.0.0.1:7001',
  133. '127.0.0.1:7002',
  134. ));
  135. $this->assertSame('127.0.0.1:7001', $ring->getByHash(PHP_INT_SIZE == 4 ? -1249390087 : 3045577209)); // uid:256
  136. $this->assertSame('127.0.0.1:7001', $ring->getByHash(PHP_INT_SIZE == 4 ? -1639106025 : 2655861271)); // uid:281
  137. $this->assertSame('127.0.0.1:7000', $ring->getByHash(PHP_INT_SIZE == 4 ? -683361581 : 3611605715)); // uid:312
  138. $this->assertSame('127.0.0.1:7001', $ring->getByHash(PHP_INT_SIZE == 4 ? -532820268 : 3762147028)); // uid:432
  139. $this->assertSame('127.0.0.1:7002', $ring->getByHash(PHP_INT_SIZE == 4 ? 618436108 : 618436108)); // uid:500
  140. $this->assertSame('127.0.0.1:7000', $ring->getByHash(PHP_INT_SIZE == 4 ? 905043399 : 905043399)); // uid:641
  141. }
  142. /**
  143. * @group disconnected
  144. */
  145. public function testGetBySlot()
  146. {
  147. $ring = $this->getSampleDistribution(array(
  148. '127.0.0.1:7000',
  149. '127.0.0.1:7001',
  150. '127.0.0.1:7002',
  151. ));
  152. $this->assertSame('127.0.0.1:7001', $ring->getBySlot(PHP_INT_SIZE == 4 ? -1255075679 : 3039891617)); // uid:256
  153. $this->assertSame('127.0.0.1:7001', $ring->getBySlot(PHP_INT_SIZE == 4 ? -1642314910 : 2652652386)); // uid:281
  154. $this->assertSame('127.0.0.1:7000', $ring->getBySlot(PHP_INT_SIZE == 4 ? -687739295 : 3607228001)); // uid:312
  155. $this->assertSame('127.0.0.1:7001', $ring->getBySlot(PHP_INT_SIZE == 4 ? -544842345 : 3750124951)); // uid:432
  156. $this->assertSame('127.0.0.1:7002', $ring->getBySlot(PHP_INT_SIZE == 4 ? 609245004 : 609245004)); // uid:500
  157. $this->assertSame('127.0.0.1:7000', $ring->getBySlot(PHP_INT_SIZE == 4 ? 902549909 : 902549909)); // uid:641
  158. // Test first and last slots
  159. $this->assertSame('127.0.0.1:7001', $ring->getBySlot(PHP_INT_SIZE == 4 ? -2096102881 : 2198864415));
  160. $this->assertSame('127.0.0.1:7002', $ring->getBySlot(PHP_INT_SIZE == 4 ? 2146453549 : 2146453549));
  161. // Test non-existing slot
  162. $this->assertNull($ring->getBySlot(0));
  163. }
  164. /**
  165. * @group disconnected
  166. */
  167. public function testCallbackToGetNodeHash()
  168. {
  169. $node = '127.0.0.1:7000';
  170. $callable = $this->getMock('stdClass', array('__invoke'));
  171. $callable
  172. ->expects($this->once())
  173. ->method('__invoke')
  174. ->with($node)
  175. ->will($this->returnValue($node));
  176. $distributor = new HashRing(HashRing::DEFAULT_REPLICAS, $callable);
  177. $distributor->add($node);
  178. $this->getNodes($distributor);
  179. }
  180. }