|
12 | 12 |
|
13 | 13 | namespace App\Tests\Entity; |
14 | 14 |
|
| 15 | +use App\Entity\Dependent; |
15 | 16 | use App\Entity\Package; |
16 | 17 | use App\Entity\PackageFreezeReason; |
17 | 18 | use App\Entity\PackageRepository; |
| 19 | +use App\Entity\Suggester; |
18 | 20 | use App\Tests\IntegrationTestCase; |
| 21 | +use Predis\Client; |
19 | 22 |
|
20 | 23 | class PackageRepositoryTest extends IntegrationTestCase |
21 | 24 | { |
@@ -197,4 +200,63 @@ public function testGetFilteredQueryBuilderExcludesSuppressedByDefault(): void |
197 | 200 | self::assertContains('vendor/spam', $withFrozen); |
198 | 201 | self::assertContains('vendor/malware', $withFrozen); |
199 | 202 | } |
| 203 | + |
| 204 | + public function testGetDependentCountIsCachedPerType(): void |
| 205 | + { |
| 206 | + $requirer = self::createPackage('test/requirer', 'https://example.org/requirer'); |
| 207 | + $devRequirer = self::createPackage('test/dev-requirer', 'https://example.org/dev-requirer'); |
| 208 | + $this->store($requirer, $devRequirer); |
| 209 | + $this->store( |
| 210 | + new Dependent($requirer, 'test/required', Dependent::TYPE_REQUIRE), |
| 211 | + new Dependent($devRequirer, 'test/required', Dependent::TYPE_REQUIRE_DEV), |
| 212 | + ); |
| 213 | + |
| 214 | + self::assertSame(2, $this->packageRepository->getDependentCount('test/required')); |
| 215 | + self::assertSame(1, $this->packageRepository->getDependentCount('test/required', Dependent::TYPE_REQUIRE)); |
| 216 | + self::assertSame(1, $this->packageRepository->getDependentCount('test/required', Dependent::TYPE_REQUIRE_DEV)); |
| 217 | + |
| 218 | + // each variant gets its own key, so the type filter cannot be served from the unfiltered count |
| 219 | + self::assertSame('2', $this->redisCache()->get('dep-count:test/required:all')); |
| 220 | + self::assertSame('1', $this->redisCache()->get('dep-count:test/required:'.Dependent::TYPE_REQUIRE)); |
| 221 | + self::assertSame('1', $this->redisCache()->get('dep-count:test/required:'.Dependent::TYPE_REQUIRE_DEV)); |
| 222 | + } |
| 223 | + |
| 224 | + public function testGetDependentCountReadsTheCacheAndIgnoresNameCasing(): void |
| 225 | + { |
| 226 | + $this->redisCache()->set('dep-count:test/required:all', '42'); |
| 227 | + |
| 228 | + self::assertSame(42, $this->packageRepository->getDependentCount('test/required')); |
| 229 | + // packageName uses a case-insensitive collation, so casing must not produce a second entry |
| 230 | + self::assertSame(42, $this->packageRepository->getDependentCount('Test/Required')); |
| 231 | + } |
| 232 | + |
| 233 | + public function testGetSuggestCountIsCached(): void |
| 234 | + { |
| 235 | + $suggester = self::createPackage('test/suggester', 'https://example.org/suggester'); |
| 236 | + $this->store($suggester); |
| 237 | + $this->store(new Suggester($suggester, 'test/suggested')); |
| 238 | + |
| 239 | + self::assertSame(1, $this->packageRepository->getSuggestCount('test/suggested')); |
| 240 | + self::assertSame('1', $this->redisCache()->get('sug-count:test/suggested')); |
| 241 | + |
| 242 | + $this->redisCache()->set('sug-count:test/suggested', '7'); |
| 243 | + self::assertSame(7, $this->packageRepository->getSuggestCount('test/suggested')); |
| 244 | + } |
| 245 | + |
| 246 | + public function testCountsCacheZeroSoUnknownPackagesDoNotRequeryEveryPageView(): void |
| 247 | + { |
| 248 | + self::assertSame(0, $this->packageRepository->getDependentCount('test/nothing-requires-this')); |
| 249 | + self::assertSame(0, $this->packageRepository->getSuggestCount('test/nothing-requires-this')); |
| 250 | + |
| 251 | + self::assertSame('0', $this->redisCache()->get('dep-count:test/nothing-requires-this:all')); |
| 252 | + self::assertSame('0', $this->redisCache()->get('sug-count:test/nothing-requires-this')); |
| 253 | + } |
| 254 | + |
| 255 | + private function redisCache(): Client |
| 256 | + { |
| 257 | + $client = static::getContainer()->get('snc_redis.cache'); |
| 258 | + self::assertInstanceOf(Client::class, $client); |
| 259 | + |
| 260 | + return $client; |
| 261 | + } |
200 | 262 | } |
0 commit comments