diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index f28c57a4d240..77d71a5afc3a 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -232,7 +232,7 @@ public function remaining($key, $maxAttempts) $attempts = $this->attempts($key); - return $maxAttempts - $attempts; + return max(0, $maxAttempts - $attempts); } /** diff --git a/tests/Cache/CacheRateLimiterTest.php b/tests/Cache/CacheRateLimiterTest.php index a4e7d5e2a099..dc85daf3ea0b 100644 --- a/tests/Cache/CacheRateLimiterTest.php +++ b/tests/Cache/CacheRateLimiterTest.php @@ -76,6 +76,18 @@ public function testHitHasNoMemoryLeak() $rateLimiter->hit('key', 1); } + public function testRemainingIsNotNegative(): void + { + $cache = m::mock(Cache::class); + $cache->shouldReceive('get')->with('key', 0)->andReturn(5); + $cache->shouldReceive('getStore')->andReturn(new ArrayStore); + + $rateLimiter = new RateLimiter($cache); + + $this->assertSame(0, $rateLimiter->remaining('key', 3)); + $this->assertSame(0, $rateLimiter->retriesLeft('key', 3)); + } + public function testRetriesLeftReturnsCorrectCount() { $cache = m::mock(Cache::class);