dbUpdater = $this->prophesize(DbUpdaterInterface::class); $this->geoLiteDbReader = $this->prophesize(Reader::class); $locker = $this->prophesize(Lock\LockFactory::class); $lock = $this->prophesize(Lock\LockInterface::class); $lock->acquire(true)->willReturn(true); $lock->release()->will(function (): void { }); $locker->createLock(Argument::type('string'))->willReturn($lock->reveal()); $this->geolocationDbUpdater = new GeolocationDbUpdater( $this->dbUpdater->reveal(), $this->geoLiteDbReader->reveal(), $locker->reveal(), ); } /** @test */ public function exceptionIsThrownWhenOlderDbDoesNotExistAndDownloadFails(): void { $mustBeUpdated = fn () => self::assertTrue(true); $prev = new RuntimeException(''); $fileExists = $this->dbUpdater->databaseFileExists()->willReturn(false); $getMeta = $this->geoLiteDbReader->metadata(); $download = $this->dbUpdater->downloadFreshCopy(null)->willThrow($prev); try { $this->geolocationDbUpdater->checkDbUpdate($mustBeUpdated); self::assertTrue(false); // If this is reached, the test will fail } catch (Throwable $e) { /** @var GeolocationDbUpdateFailedException $e */ self::assertInstanceOf(GeolocationDbUpdateFailedException::class, $e); self::assertSame($prev, $e->getPrevious()); self::assertFalse($e->olderDbExists()); } $fileExists->shouldHaveBeenCalledOnce(); $getMeta->shouldNotHaveBeenCalled(); $download->shouldHaveBeenCalledOnce(); } /** * @test * @dataProvider provideBigDays */ public function exceptionIsThrownWhenOlderDbIsTooOldAndDownloadFails(int $days): void { $fileExists = $this->dbUpdater->databaseFileExists()->willReturn(true); $getMeta = $this->geoLiteDbReader->metadata()->willReturn(new Metadata([ 'binary_format_major_version' => '', 'binary_format_minor_version' => '', 'build_epoch' => Chronos::now()->subDays($days)->getTimestamp(), 'database_type' => '', 'languages' => '', 'description' => '', 'ip_version' => '', 'node_count' => 1, 'record_size' => 4, ])); $prev = new RuntimeException(''); $download = $this->dbUpdater->downloadFreshCopy(null)->willThrow($prev); try { $this->geolocationDbUpdater->checkDbUpdate(); self::assertTrue(false); // If this is reached, the test will fail } catch (Throwable $e) { /** @var GeolocationDbUpdateFailedException $e */ self::assertInstanceOf(GeolocationDbUpdateFailedException::class, $e); self::assertSame($prev, $e->getPrevious()); self::assertTrue($e->olderDbExists()); } $fileExists->shouldHaveBeenCalledOnce(); $getMeta->shouldHaveBeenCalledOnce(); $download->shouldHaveBeenCalledOnce(); } public function provideBigDays(): iterable { yield [36]; yield [50]; yield [75]; yield [100]; } /** * @test * @dataProvider provideSmallDays */ public function databaseIsNotUpdatedIfItIsYoungerThanOneWeek(int $days): void { $fileExists = $this->dbUpdater->databaseFileExists()->willReturn(true); $getMeta = $this->geoLiteDbReader->metadata()->willReturn(new Metadata([ 'binary_format_major_version' => '', 'binary_format_minor_version' => '', 'build_epoch' => Chronos::now()->subDays($days)->getTimestamp(), 'database_type' => '', 'languages' => '', 'description' => '', 'ip_version' => '', 'node_count' => 1, 'record_size' => 4, ])); $download = $this->dbUpdater->downloadFreshCopy(null)->will(function (): void { }); $this->geolocationDbUpdater->checkDbUpdate(); $fileExists->shouldHaveBeenCalledOnce(); $getMeta->shouldHaveBeenCalledOnce(); $download->shouldNotHaveBeenCalled(); } public function provideSmallDays(): iterable { return map(range(0, 34), fn (int $days) => [$days]); } }