| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- <?php
- declare(strict_types=1);
- namespace App\Tests\Unit\Enrichment;
- use App\Domain\Ip\IpAddress;
- use App\Domain\Time\Clock;
- use App\Domain\Time\SystemClock;
- use App\Infrastructure\Enrichment\MaxMindRecordAdapter;
- use App\Infrastructure\Enrichment\MmdbEnrichmentService;
- use Monolog\Handler\TestHandler;
- use Monolog\Logger;
- use PHPUnit\Framework\TestCase;
- /**
- * Drives MmdbEnrichmentService against the vendored MaxMind test
- * fixtures (Apache-2.0). Covers the load → lookup → result → reload
- * lifecycle plus the warn-once-on-missing-DB invariant.
- */
- final class MmdbEnrichmentServiceTest extends TestCase
- {
- private const COUNTRY_DB = __DIR__ . '/../../Fixtures/geoip/country.mmdb';
- private const ASN_DB = __DIR__ . '/../../Fixtures/geoip/asn.mmdb';
- public function testLooksUpKnownIpv4Fixture(): void
- {
- $service = $this->makeService(self::COUNTRY_DB, self::ASN_DB);
- $result = $service->enrich(IpAddress::fromString('81.2.69.142'));
- self::assertSame('GB', $result->countryCode);
- // The fixture's ASN db doesn't carry every test IP — country alone is the load-bearing assertion.
- }
- public function testIpv6Lookup(): void
- {
- $service = $this->makeService(self::COUNTRY_DB, self::ASN_DB);
- // The MaxMind fixture covers v4-mapped v6 of 81.2.69.142.
- $result = $service->enrich(IpAddress::fromString('::ffff:81.2.69.142'));
- self::assertSame('GB', $result->countryCode);
- }
- public function testUnknownIpReturnsEmpty(): void
- {
- $service = $this->makeService(self::COUNTRY_DB, self::ASN_DB);
- // A reserved-but-not-in-fixture IP.
- $result = $service->enrich(IpAddress::fromString('192.0.2.99'));
- self::assertNull($result->countryCode);
- self::assertNull($result->asn);
- self::assertTrue($result->isEmpty());
- }
- public function testMissingDbWarnsOnceAndReturnsEmpty(): void
- {
- $logger = new Logger('t');
- $handler = new TestHandler();
- $logger->pushHandler($handler);
- $service = new MmdbEnrichmentService(
- countryDbPath: '/nonexistent/country.mmdb',
- asnDbPath: '/nonexistent/asn.mmdb',
- adapter: new MaxMindRecordAdapter(),
- clock: new SystemClock(),
- logger: $logger,
- );
- // Two lookups should still produce only one warning.
- $a = $service->enrich(IpAddress::fromString('1.2.3.4'));
- $b = $service->enrich(IpAddress::fromString('5.6.7.8'));
- self::assertTrue($a->isEmpty());
- self::assertTrue($b->isEmpty());
- self::assertFalse($service->isReady());
- $messages = array_map(static fn ($r): string => $r->message, $handler->getRecords());
- $matches = array_filter($messages, static fn (string $m): bool => $m === 'geoip_db_unavailable');
- self::assertCount(1, $matches);
- }
- public function testReloadReadersClearsState(): void
- {
- $service = $this->makeService(self::COUNTRY_DB, self::ASN_DB);
- $service->enrich(IpAddress::fromString('81.2.69.142'));
- $service->reloadReaders();
- // Should still work after reload.
- $result = $service->enrich(IpAddress::fromString('81.2.69.142'));
- self::assertSame('GB', $result->countryCode);
- }
- private function makeService(string $country, string $asn, ?Clock $clock = null): MmdbEnrichmentService
- {
- $logger = new Logger('t');
- $logger->pushHandler(new TestHandler());
- return new MmdbEnrichmentService(
- countryDbPath: $country,
- asnDbPath: $asn,
- adapter: new MaxMindRecordAdapter(),
- clock: $clock ?? new SystemClock(),
- logger: $logger,
- );
- }
- }
|