Fix errors with some of files

This commit is contained in:
DariusIII
2026-04-21 11:24:14 +02:00
parent 02b0727c89
commit 6a03c6b2ad
8 changed files with 506 additions and 23 deletions
+57
View File
@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use App\Support\FilenameSanitizer;
use PHPUnit\Framework\TestCase;
final class FilenameSanitizerTest extends TestCase
{
public function test_sanitize_replaces_forbidden_and_unicode_path_characters(): void
{
$sanitized = FilenameSanitizer::sanitize(' Show / Name \\ Part Alt Dual FullBack ');
$this->assertSame('Show_Name_Part_Alt_Dual_Full_Back', $sanitized);
}
public function test_sanitize_removes_control_characters_and_reserved_windows_characters(): void
{
$sanitized = FilenameSanitizer::sanitize("Bad\0Name:*?\"<>|\x1FTest");
$this->assertSame('BadName_Test', $sanitized);
}
public function test_sanitize_collapses_commas_and_whitespace_to_single_underscores(): void
{
$sanitized = FilenameSanitizer::sanitize(' The File, Name , Part 2 ');
$this->assertSame('The_File_Name_Part_2', $sanitized);
}
public function test_sanitize_uses_fallback_for_empty_or_dot_only_names(): void
{
$this->assertSame('release-123', FilenameSanitizer::sanitize(null, 'release-123'));
$this->assertSame('release-123', FilenameSanitizer::sanitize('', 'release-123'));
$this->assertSame('release-123', FilenameSanitizer::sanitize('...___---', 'release-123'));
}
public function test_sanitize_truncates_to_safe_length(): void
{
$sanitized = FilenameSanitizer::sanitize(str_repeat('a', 300));
$this->assertSame(200, mb_strlen($sanitized));
$this->assertSame(str_repeat('a', 200), $sanitized);
}
public function test_ascii_fallback_returns_safe_ascii_filename(): void
{
$fallback = FilenameSanitizer::asciiFallback('Résumé/Season 1\\Finale');
$this->assertMatchesRegularExpression('/^[\x20-\x7E]+$/', $fallback);
$this->assertStringNotContainsString('/', $fallback);
$this->assertStringNotContainsString('\\', $fallback);
$this->assertSame($fallback, FilenameSanitizer::asciiFallback($fallback));
}
}
+149
View File
@@ -0,0 +1,149 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use App\Services\Nzb\NzbService;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
final class NzbServicePathResolutionTest extends TestCase
{
public function test_select_preferred_base_path_prefers_existing_runtime_storage_path_for_foreign_storage_root(): void
{
$tempDir = sys_get_temp_dir().'/nzb-service-'.uniqid('', true);
$configuredPath = $tempDir.'/foreign-app/storage/nzb/';
$runtimePath = $tempDir.'/runtime-app/storage/nzb/';
mkdir($runtimePath, 0777, true);
try {
$service = $this->makeServiceWithoutConstructor();
$preferredPath = \Closure::bind(
fn (array $paths): string => $this->selectPreferredNzbBasePath($paths),
$service,
NzbService::class
)([$configuredPath, $runtimePath]);
$this->assertSame($runtimePath, $preferredPath);
} finally {
$this->deleteDirectory($tempDir);
}
}
public function test_nzb_path_returns_existing_file_from_alternate_candidate_base_paths(): void
{
$tempDir = sys_get_temp_dir().'/nzb-path-'.uniqid('', true);
$guid = '4aabfe07-daff-4d28-9d1d-d2a4ab7b6511';
$configuredPath = $tempDir.'/foreign-app/storage/nzb/';
$runtimePath = $tempDir.'/runtime-app/storage/nzb/';
$expectedFile = $runtimePath.'4/a/a/b/'.$guid.'.nzb.gz';
mkdir(dirname($expectedFile), 0777, true);
file_put_contents($expectedFile, 'test');
try {
$service = $this->makeServiceWithoutConstructor();
\Closure::bind(
function (int $splitLevel, string $primaryPath, array $paths): void {
$this->nzbSplitLevel = $splitLevel;
$this->siteNzbPath = $primaryPath;
$this->siteNzbPaths = $paths;
},
$service,
NzbService::class
)(4, $configuredPath, [$configuredPath, $runtimePath]);
$this->assertSame($expectedFile, $service->nzbPath($guid));
} finally {
$this->deleteDirectory($tempDir);
}
}
public function test_nzb_path_honors_split_level_one_when_searching_candidate_paths(): void
{
$tempDir = sys_get_temp_dir().'/nzb-path-split-one-'.uniqid('', true);
$guid = '4aabfe07-daff-4d28-9d1d-d2a4ab7b6511';
$configuredPath = $tempDir.'/foreign-app/storage/nzb/';
$runtimePath = $tempDir.'/runtime-app/storage/nzb/';
$expectedFile = $runtimePath.'4/'.$guid.'.nzb.gz';
mkdir(dirname($expectedFile), 0777, true);
file_put_contents($expectedFile, 'test');
try {
$service = $this->makeServiceWithoutConstructor();
\Closure::bind(
function (int $splitLevel, string $primaryPath, array $paths): void {
$this->nzbSplitLevel = $splitLevel;
$this->siteNzbPath = $primaryPath;
$this->siteNzbPaths = $paths;
},
$service,
NzbService::class
)(1, $configuredPath, [$configuredPath, $runtimePath]);
$this->assertSame($expectedFile, $service->nzbPath($guid));
} finally {
$this->deleteDirectory($tempDir);
}
}
public function test_nzb_path_works_with_existing_resources_nzb_base_path(): void
{
$tempDir = sys_get_temp_dir().'/nzb-path-resources-'.uniqid('', true);
$guid = '4aabfe07-daff-4d28-9d1d-d2a4ab7b6511';
$configuredPath = $tempDir.'/resources/nzb/';
$storagePath = $tempDir.'/storage/nzb/';
$expectedFile = $configuredPath.'4/'.$guid.'.nzb.gz';
$configuredLinkTarget = rtrim($configuredPath, '/');
$storageLinkPath = rtrim($storagePath, '/');
mkdir(dirname($expectedFile), 0777, true);
mkdir(dirname($storageLinkPath), 0777, true);
symlink($configuredLinkTarget, $storageLinkPath);
file_put_contents($expectedFile, 'test');
try {
$service = $this->makeServiceWithoutConstructor();
\Closure::bind(
function (int $splitLevel, string $primaryPath, array $paths): void {
$this->nzbSplitLevel = $splitLevel;
$this->siteNzbPath = $primaryPath;
$this->siteNzbPaths = $paths;
},
$service,
NzbService::class
)(1, $configuredPath, [$configuredPath, $storagePath]);
$this->assertSame($expectedFile, $service->nzbPath($guid));
} finally {
$this->deleteDirectory($tempDir);
}
}
private function makeServiceWithoutConstructor(): NzbService
{
return (new ReflectionClass(NzbService::class))->newInstanceWithoutConstructor();
}
private function deleteDirectory(string $path): void
{
if (! is_dir($path)) {
return;
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $item) {
if ($item->isDir()) {
rmdir($item->getPathname());
} else {
unlink($item->getPathname());
}
}
rmdir($path);
}
}
@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Support;
use App\Support\FilenameSanitizer;
use PHPUnit\Framework\TestCase;
final class FilenameSanitizerTest extends TestCase
{
public function test_sanitize_replaces_forbidden_and_unicode_path_characters(): void
{
$sanitized = FilenameSanitizer::sanitize(' Show / Name \\ Part Alt Dual FullBack ');
$this->assertSame('Show_Name_Part_Alt_Dual_Full_Back', $sanitized);
}
public function test_sanitize_removes_control_characters_and_reserved_windows_characters(): void
{
$sanitized = FilenameSanitizer::sanitize("Bad\0Name:*?\"<>|\x1FTest");
$this->assertSame('BadName_Test', $sanitized);
}
public function test_sanitize_collapses_commas_and_whitespace_to_single_underscores(): void
{
$sanitized = FilenameSanitizer::sanitize(' The File, Name , Part 2 ');
$this->assertSame('The_File_Name_Part_2', $sanitized);
}
public function test_sanitize_uses_fallback_for_empty_or_dot_only_names(): void
{
$this->assertSame('release-123', FilenameSanitizer::sanitize(null, 'release-123'));
$this->assertSame('release-123', FilenameSanitizer::sanitize('', 'release-123'));
$this->assertSame('release-123', FilenameSanitizer::sanitize('...___---', 'release-123'));
}
public function test_sanitize_truncates_to_safe_length(): void
{
$sanitized = FilenameSanitizer::sanitize(str_repeat('a', 300));
$this->assertSame(200, mb_strlen($sanitized));
$this->assertSame(str_repeat('a', 200), $sanitized);
}
public function test_ascii_fallback_returns_safe_ascii_filename(): void
{
$fallback = FilenameSanitizer::asciiFallback('Résumé/Season 1\\Finale');
$this->assertMatchesRegularExpression('/^[\x20-\x7E]+$/', $fallback);
$this->assertStringNotContainsString('/', $fallback);
$this->assertStringNotContainsString('\\', $fallback);
$this->assertSame($fallback, FilenameSanitizer::asciiFallback($fallback));
}
}