AbstractRedisSessionHandlerTestCase.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.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 Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler;
  13. /**
  14. * @requires extension redis
  15. *
  16. * @group time-sensitive
  17. */
  18. abstract class AbstractRedisSessionHandlerTestCase extends TestCase
  19. {
  20. protected const PREFIX = 'prefix_';
  21. /**
  22. * @var RedisSessionHandler
  23. */
  24. protected $storage;
  25. /**
  26. * @var \Redis|\RedisArray|\RedisCluster|\Predis\Client
  27. */
  28. protected $redisClient;
  29. /**
  30. * @return \Redis|\RedisArray|\RedisCluster|\Predis\Client
  31. */
  32. abstract protected function createRedisClient(string $host): object;
  33. protected function setUp(): void
  34. {
  35. parent::setUp();
  36. if (!\extension_loaded('redis')) {
  37. self::markTestSkipped('Extension redis required.');
  38. }
  39. try {
  40. (new \Redis())->connect(...explode(':', getenv('REDIS_HOST')));
  41. } catch (\Exception $e) {
  42. self::markTestSkipped($e->getMessage());
  43. }
  44. $host = getenv('REDIS_HOST') ?: 'localhost';
  45. $this->redisClient = $this->createRedisClient($host);
  46. $this->storage = new RedisSessionHandler(
  47. $this->redisClient,
  48. ['prefix' => self::PREFIX]
  49. );
  50. }
  51. protected function tearDown(): void
  52. {
  53. $this->redisClient = null;
  54. $this->storage = null;
  55. parent::tearDown();
  56. }
  57. public function testOpenSession()
  58. {
  59. $this->assertTrue($this->storage->open('', ''));
  60. }
  61. public function testCloseSession()
  62. {
  63. $this->assertTrue($this->storage->close());
  64. }
  65. public function testReadSession()
  66. {
  67. $this->redisClient->set(self::PREFIX.'id1', null);
  68. $this->redisClient->set(self::PREFIX.'id2', 'abc123');
  69. $this->assertEquals('', $this->storage->read('id1'));
  70. $this->assertEquals('abc123', $this->storage->read('id2'));
  71. }
  72. public function testWriteSession()
  73. {
  74. $this->assertTrue($this->storage->write('id', 'data'));
  75. $this->assertTrue((bool) $this->redisClient->exists(self::PREFIX.'id'));
  76. $this->assertEquals('data', $this->redisClient->get(self::PREFIX.'id'));
  77. }
  78. public function testUseSessionGcMaxLifetimeAsTimeToLive()
  79. {
  80. $this->storage->write('id', 'data');
  81. $ttl = $this->redisClient->ttl(self::PREFIX.'id');
  82. $this->assertLessThanOrEqual(\ini_get('session.gc_maxlifetime'), $ttl);
  83. $this->assertGreaterThanOrEqual(0, $ttl);
  84. }
  85. public function testDestroySession()
  86. {
  87. $this->redisClient->set(self::PREFIX.'id', 'foo');
  88. $this->assertTrue((bool) $this->redisClient->exists(self::PREFIX.'id'));
  89. $this->assertTrue($this->storage->destroy('id'));
  90. $this->assertFalse((bool) $this->redisClient->exists(self::PREFIX.'id'));
  91. }
  92. public function testGcSession()
  93. {
  94. $this->assertIsInt($this->storage->gc(123));
  95. }
  96. public function testUpdateTimestamp()
  97. {
  98. $lowTtl = 10;
  99. $this->redisClient->setex(self::PREFIX.'id', $lowTtl, 'foo');
  100. $this->storage->updateTimestamp('id', 'data');
  101. $this->assertGreaterThan($lowTtl, $this->redisClient->ttl(self::PREFIX.'id'));
  102. }
  103. /**
  104. * @dataProvider getOptionFixtures
  105. */
  106. public function testSupportedParam(array $options, bool $supported)
  107. {
  108. try {
  109. new RedisSessionHandler($this->redisClient, $options);
  110. $this->assertTrue($supported);
  111. } catch (\InvalidArgumentException $e) {
  112. $this->assertFalse($supported);
  113. }
  114. }
  115. public static function getOptionFixtures(): array
  116. {
  117. return [
  118. [['prefix' => 'session'], true],
  119. [['ttl' => 1000], true],
  120. [['prefix' => 'sfs', 'ttl' => 1000], true],
  121. [['prefix' => 'sfs', 'foo' => 'bar'], false],
  122. [['ttl' => 'sfs', 'foo' => 'bar'], false],
  123. ];
  124. }
  125. /**
  126. * @dataProvider getTtlFixtures
  127. */
  128. public function testUseTtlOption(int $ttl)
  129. {
  130. $options = [
  131. 'prefix' => self::PREFIX,
  132. 'ttl' => $ttl,
  133. ];
  134. $handler = new RedisSessionHandler($this->redisClient, $options);
  135. $handler->write('id', 'data');
  136. $redisTtl = $this->redisClient->ttl(self::PREFIX.'id');
  137. $this->assertLessThan($redisTtl, $ttl - 5);
  138. $this->assertGreaterThan($redisTtl, $ttl + 5);
  139. }
  140. public static function getTtlFixtures(): array
  141. {
  142. return [
  143. ['ttl' => 5000],
  144. ['ttl' => 120],
  145. ['ttl' => 60],
  146. ];
  147. }
  148. }