repoRoot() . '/doc/reference_samples/does-not-exist.proplaylist'; $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage(sprintf('Playlist file not found: %s', $filePath)); ProPlaylistReader::read($filePath); } #[Test] public function readThrowsOnEmptyFile(): void { $filePath = tempnam(sys_get_temp_dir(), 'proplaylist-empty-'); if ($filePath === false) { self::fail('Unable to create temporary test file.'); } try { $this->expectException(RuntimeException::class); $this->expectExceptionMessage(sprintf('Playlist file is empty: %s', $filePath)); ProPlaylistReader::read($filePath); } finally { @unlink($filePath); } } #[Test] public function readThrowsOnInvalidZipFormat(): void { $filePath = tempnam(sys_get_temp_dir(), 'proplaylist-invalid-'); if ($filePath === false) { self::fail('Unable to create temporary test file.'); } try { file_put_contents($filePath, 'not-a-zip-archive'); $this->expectException(RuntimeException::class); ProPlaylistReader::read($filePath); } finally { @unlink($filePath); } } #[Test] public function readReturnsPlaylistArchiveForTestPlaylist(): void { $archive = ProPlaylistReader::read($this->repoRoot() . '/doc/reference_samples/TestPlaylist.proplaylist'); $this->assertInstanceOf(PlaylistArchive::class, $archive); $this->assertSame('TestPlaylist', $archive->getName()); $this->assertGreaterThan(0, $archive->getEntryCount()); } #[Test] public function readExtractsEmbeddedFilesFromTestPlaylist(): void { $archive = ProPlaylistReader::read($this->repoRoot() . '/doc/reference_samples/TestPlaylist.proplaylist'); $embeddedFiles = $archive->getEmbeddedFiles(); $this->assertNotEmpty($embeddedFiles); $this->assertArrayNotHasKey('data', $embeddedFiles); $this->assertGreaterThanOrEqual(2, count($archive->getEmbeddedProFiles())); $this->assertGreaterThanOrEqual(1, count($archive->getEmbeddedMediaFiles())); } #[Test] public function readParsesEmbeddedSongsLazilyFromTestPlaylist(): void { $archive = ProPlaylistReader::read($this->repoRoot() . '/doc/reference_samples/TestPlaylist.proplaylist'); $embeddedProFiles = $archive->getEmbeddedProFiles(); $this->assertNotEmpty($embeddedProFiles); $firstProFilename = array_key_first($embeddedProFiles); $this->assertNotNull($firstProFilename); $song = $archive->getEmbeddedSong((string) $firstProFilename); $this->assertNotNull($song); $this->assertNotSame('', $song->getName()); } #[Test] public function readHandlesGottesdienstPlaylist(): void { $archive = ProPlaylistReader::read($this->repoRoot() . '/doc/reference_samples/ExamplePlaylists/Gottesdienst.proplaylist'); $this->assertNotSame('', $archive->getName()); $this->assertGreaterThan(0, $archive->getEntryCount()); $this->assertNotEmpty($archive->getEmbeddedFiles()); } #[Test] public function readHandlesGottesdienst2Playlist(): void { $archive = ProPlaylistReader::read($this->repoRoot() . '/doc/reference_samples/ExamplePlaylists/Gottesdienst 2.proplaylist'); $this->assertNotSame('', $archive->getName()); $this->assertGreaterThan(0, $archive->getEntryCount()); $this->assertNotEmpty($archive->getEmbeddedFiles()); } #[Test] public function readHandlesGottesdienst3Playlist(): void { $archive = ProPlaylistReader::read($this->repoRoot() . '/doc/reference_samples/ExamplePlaylists/Gottesdienst 3.proplaylist'); $this->assertNotSame('', $archive->getName()); $this->assertGreaterThan(0, $archive->getEntryCount()); $this->assertNotEmpty($archive->getEmbeddedFiles()); } #[Test] public function readCleansUpTempFileWhenZipOpenFails(): void { $filePath = tempnam(sys_get_temp_dir(), 'proplaylist-badzip-'); if ($filePath === false) { self::fail('Unable to create temporary test file.'); } $before = glob(sys_get_temp_dir() . '/proplaylist-*'); if ($before === false) { $before = []; } try { file_put_contents($filePath, str_repeat('x', 128)); try { ProPlaylistReader::read($filePath); self::fail('Expected RuntimeException was not thrown.'); } catch (RuntimeException) { } $after = glob(sys_get_temp_dir() . '/proplaylist-*'); if ($after === false) { $after = []; } sort($before); sort($after); $this->assertSame($before, $after); } finally { @unlink($filePath); } } #[Test] public function readThrowsWhenDataEntryIsMissing(): void { $filePath = tempnam(sys_get_temp_dir(), 'proplaylist-nodata-'); if ($filePath === false) { self::fail('Unable to create temporary test file.'); } $zip = new \ZipArchive(); try { $openResult = $zip->open($filePath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); $this->assertTrue($openResult === true, sprintf('Unable to open zip for test, code: %s', (string) $openResult)); $zip->addFromString('song1.pro', 'dummy-song'); $zip->close(); $this->expectException(RuntimeException::class); $this->expectExceptionMessage(sprintf('Missing data entry in playlist archive: %s', $filePath)); ProPlaylistReader::read($filePath); } finally { @unlink($filePath); } } }