parser = new DumpFilenameParser(); } public function testFormatProducesExpectedPattern(): void { $dateTime = new \DateTimeImmutable('2026-09-14 15:04:05'); self::assertSame('dump_2026-09-14_15-04-05.sql.gz', $this->parser->format($dateTime)); } public function testParseRoundTripsWithFormat(): void { $dateTime = new \DateTimeImmutable('2026-09-14 15:04:05'); $filename = $this->parser->format($dateTime); self::assertEquals($dateTime, $this->parser->parse($filename)); } /** * @dataProvider invalidFilenameProvider */ public function testParseRejectsInvalidFilenames(string $filename): void { self::assertNull($this->parser->parse($filename)); } public static function invalidFilenameProvider(): iterable { yield 'wrong extension' => ['dump_2026-09-14_15-04-05.sql']; yield 'no prefix' => ['2026-09-14_15-04-05.sql.gz']; yield 'path traversal' => ['../dump_2026-09-14_15-04-05.sql.gz']; yield 'garbage' => ['not-a-dump.sql.gz']; yield 'empty' => ['']; } public function testIsValid(): void { self::assertTrue($this->parser->isValid('dump_2026-09-14_15-04-05.sql.gz')); self::assertFalse($this->parser->isValid('../etc/passwd')); } }