RedisCacheLockTest.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php
  2. namespace Illuminate\Tests\Integration\Cache;
  3. use Exception;
  4. use Illuminate\Foundation\Testing\Concerns\InteractsWithRedis;
  5. use Illuminate\Support\Carbon;
  6. use Illuminate\Support\Facades\Cache;
  7. use Orchestra\Testbench\TestCase;
  8. class RedisCacheLockTest extends TestCase
  9. {
  10. use InteractsWithRedis;
  11. protected function setUp(): void
  12. {
  13. parent::setUp();
  14. $this->setUpRedis();
  15. }
  16. protected function tearDown(): void
  17. {
  18. parent::tearDown();
  19. $this->tearDownRedis();
  20. }
  21. public function testRedisLocksCanBeAcquiredAndReleased()
  22. {
  23. Cache::store('redis')->lock('foo')->forceRelease();
  24. $lock = Cache::store('redis')->lock('foo', 10);
  25. $this->assertTrue($lock->get());
  26. $this->assertFalse(Cache::store('redis')->lock('foo', 10)->get());
  27. $lock->release();
  28. $lock = Cache::store('redis')->lock('foo', 10);
  29. $this->assertTrue($lock->get());
  30. $this->assertFalse(Cache::store('redis')->lock('foo', 10)->get());
  31. Cache::store('redis')->lock('foo')->release();
  32. }
  33. public function testRedisLockCanHaveASeparateConnection()
  34. {
  35. $this->app['config']->set('cache.stores.redis.lock_connection', 'default');
  36. $this->assertSame('default', Cache::store('redis')->lock('foo')->getConnectionName());
  37. }
  38. public function testRedisLocksCanBlockForSeconds()
  39. {
  40. Carbon::setTestNow();
  41. Cache::store('redis')->lock('foo')->forceRelease();
  42. $this->assertSame('taylor', Cache::store('redis')->lock('foo', 10)->block(1, function () {
  43. return 'taylor';
  44. }));
  45. Cache::store('redis')->lock('foo')->forceRelease();
  46. $this->assertTrue(Cache::store('redis')->lock('foo', 10)->block(1));
  47. }
  48. public function testConcurrentRedisLocksAreReleasedSafely()
  49. {
  50. Cache::store('redis')->lock('foo')->forceRelease();
  51. $firstLock = Cache::store('redis')->lock('foo', 1);
  52. $this->assertTrue($firstLock->get());
  53. sleep(2);
  54. $secondLock = Cache::store('redis')->lock('foo', 10);
  55. $this->assertTrue($secondLock->get());
  56. $firstLock->release();
  57. $this->assertFalse(Cache::store('redis')->lock('foo')->get());
  58. }
  59. public function testRedisLocksWithFailedBlockCallbackAreReleased()
  60. {
  61. Cache::store('redis')->lock('foo')->forceRelease();
  62. $firstLock = Cache::store('redis')->lock('foo', 10);
  63. try {
  64. $firstLock->block(1, function () {
  65. throw new Exception('failed');
  66. });
  67. } catch (Exception $e) {
  68. // Not testing the exception, just testing the lock
  69. // is released regardless of the how the exception
  70. // thrown by the callback was handled.
  71. }
  72. $secondLock = Cache::store('redis')->lock('foo', 1);
  73. $this->assertTrue($secondLock->get());
  74. }
  75. public function testRedisLocksCanBeReleasedUsingOwnerToken()
  76. {
  77. Cache::store('redis')->lock('foo')->forceRelease();
  78. $firstLock = Cache::store('redis')->lock('foo', 10);
  79. $this->assertTrue($firstLock->get());
  80. $owner = $firstLock->owner();
  81. $secondLock = Cache::store('redis')->restoreLock('foo', $owner);
  82. $secondLock->release();
  83. $this->assertTrue(Cache::store('redis')->lock('foo')->get());
  84. }
  85. }