Fixed: basePath self→static binding, namespace detection, event wiring,
SQLite cache, file cache driver. All Mod Boot classes converted to
$listens pattern for lifecycle event discovery.
Working endpoints:
- /v1/explorer/info — live chain height, difficulty, aliases
- /v1/explorer/stats — formatted chain statistics
- /v1/names/directory — alias directory grouped by type
- /v1/names/available/{name} — name availability check
- /v1/names/lookup/{name} — name details
Co-Authored-By: Charon <charon@lethean.io>
287 lines
8.6 KiB
PHP
287 lines
8.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* Core PHP Framework
|
|
*
|
|
* Licensed under the European Union Public Licence (EUPL) v1.2.
|
|
* See LICENSE file for details.
|
|
*/
|
|
|
|
namespace Core\Tests\Feature;
|
|
|
|
use Core\Cdn\Models\StorageOffload as StorageOffloadModel;
|
|
use Core\Cdn\Services\StorageOffload as StorageOffloadService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Config;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Tests\TestCase;
|
|
|
|
class OffloadMigrateCommandTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected string $testDirectory;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// Enable offload for testing
|
|
Config::set('offload.enabled', true);
|
|
Config::set('offload.disk', 'testing');
|
|
Config::set('offload.keep_local', false);
|
|
|
|
Config::set('filesystems.disks.testing', [
|
|
'driver' => 'local',
|
|
'root' => storage_path('framework/testing/offload'),
|
|
'url' => env('APP_URL').'/testing',
|
|
'visibility' => 'public',
|
|
]);
|
|
|
|
// Rebind the service so it picks up the new config
|
|
$this->app->forgetInstance(StorageOffloadService::class);
|
|
$this->app->bind(StorageOffloadService::class, function () {
|
|
return new StorageOffloadService;
|
|
});
|
|
|
|
// Create test directory with files
|
|
$this->testDirectory = storage_path('framework/testing/migrate-test');
|
|
@mkdir($this->testDirectory, 0755, true);
|
|
|
|
// Create test files
|
|
file_put_contents($this->testDirectory.'/image1.jpg', 'image content 1');
|
|
file_put_contents($this->testDirectory.'/image2.png', 'image content 2');
|
|
file_put_contents($this->testDirectory.'/document.pdf', 'pdf content');
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
// Clean up test directory recursively
|
|
if (is_dir($this->testDirectory)) {
|
|
$this->deleteDirectory($this->testDirectory);
|
|
}
|
|
|
|
// Clean up testing disk
|
|
Storage::disk('testing')->deleteDirectory('');
|
|
|
|
parent::tearDown();
|
|
}
|
|
|
|
/**
|
|
* Recursively delete a directory.
|
|
*/
|
|
protected function deleteDirectory(string $dir): void
|
|
{
|
|
if (! is_dir($dir)) {
|
|
return;
|
|
}
|
|
|
|
$items = glob($dir.'/*');
|
|
foreach ($items as $item) {
|
|
if (is_dir($item)) {
|
|
$this->deleteDirectory($item);
|
|
} else {
|
|
@unlink($item);
|
|
}
|
|
}
|
|
|
|
@rmdir($dir);
|
|
}
|
|
|
|
public function test_command_fails_when_offload_disabled(): void
|
|
{
|
|
Config::set('offload.enabled', false);
|
|
|
|
$this->artisan('offload:migrate', ['path' => $this->testDirectory])
|
|
->expectsOutput('Storage offload is not enabled in configuration.')
|
|
->assertExitCode(1);
|
|
}
|
|
|
|
public function test_command_fails_for_non_existent_directory(): void
|
|
{
|
|
$this->artisan('offload:migrate', ['path' => '/nonexistent/path'])
|
|
->assertExitCode(1);
|
|
}
|
|
|
|
public function test_command_can_migrate_files_with_dry_run(): void
|
|
{
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--dry-run' => true,
|
|
'--force' => true,
|
|
])
|
|
->expectsOutput('DRY RUN MODE - No files will be offloaded')
|
|
->assertExitCode(0);
|
|
|
|
// Files should still exist locally
|
|
$this->assertFileExists($this->testDirectory.'/image1.jpg');
|
|
$this->assertFileExists($this->testDirectory.'/image2.png');
|
|
|
|
// No database records should be created
|
|
$this->assertEquals(0, StorageOffloadModel::count());
|
|
}
|
|
|
|
public function test_command_can_migrate_files(): void
|
|
{
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--force' => true,
|
|
])
|
|
->assertExitCode(0);
|
|
|
|
// Files should be offloaded
|
|
$this->assertEquals(3, StorageOffloadModel::count());
|
|
|
|
// Files should exist on remote storage
|
|
$records = StorageOffloadModel::all();
|
|
foreach ($records as $record) {
|
|
$this->assertTrue(Storage::disk('testing')->exists($record->remote_path));
|
|
}
|
|
}
|
|
|
|
public function test_command_respects_category_option(): void
|
|
{
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--category' => 'page',
|
|
'--force' => true,
|
|
])
|
|
->assertExitCode(0);
|
|
|
|
$records = StorageOffloadModel::all();
|
|
foreach ($records as $record) {
|
|
$this->assertEquals('page', $record->category);
|
|
}
|
|
}
|
|
|
|
public function test_command_respects_allowed_extensions(): void
|
|
{
|
|
Config::set('offload.allowed_extensions', ['jpg', 'png']);
|
|
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--force' => true,
|
|
])
|
|
->assertExitCode(0);
|
|
|
|
// Only jpg and png files should be offloaded (not pdf)
|
|
$this->assertEquals(2, StorageOffloadModel::count());
|
|
}
|
|
|
|
public function test_command_respects_max_file_size(): void
|
|
{
|
|
// Create large file
|
|
$largeFile = $this->testDirectory.'/large.jpg';
|
|
file_put_contents($largeFile, str_repeat('x', 10000));
|
|
|
|
Config::set('offload.max_file_size', 100); // 100 bytes
|
|
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--force' => true,
|
|
])
|
|
->assertExitCode(0);
|
|
|
|
// Large file should not be offloaded
|
|
$largeFileRecord = StorageOffloadModel::where('local_path', $largeFile)->first();
|
|
$this->assertNull($largeFileRecord);
|
|
}
|
|
|
|
public function test_command_skips_already_offloaded_files(): void
|
|
{
|
|
// Offload one file first
|
|
$service = app(StorageOffloadService::class);
|
|
$service->upload($this->testDirectory.'/image1.jpg', null, 'media');
|
|
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--force' => true,
|
|
])
|
|
->assertExitCode(0);
|
|
|
|
// Should still be 3 total (not 4 with duplicate)
|
|
$this->assertEquals(3, StorageOffloadModel::count());
|
|
}
|
|
|
|
public function test_command_with_only_missing_flag(): void
|
|
{
|
|
// Offload one file first
|
|
$service = app(StorageOffloadService::class);
|
|
$service->upload($this->testDirectory.'/image1.jpg', null, 'media');
|
|
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--only-missing' => true,
|
|
'--force' => true,
|
|
])
|
|
->assertExitCode(0);
|
|
|
|
// Should offload the 2 missing files
|
|
$this->assertEquals(3, StorageOffloadModel::count());
|
|
}
|
|
|
|
public function test_command_displays_summary_table(): void
|
|
{
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--force' => true,
|
|
])
|
|
->expectsTable(
|
|
['Status', 'Count'],
|
|
[
|
|
['Processed', 3],
|
|
['Failed', 0],
|
|
['Skipped', 0],
|
|
['Total', 3],
|
|
]
|
|
)
|
|
->assertExitCode(0);
|
|
}
|
|
|
|
public function test_command_defaults_to_storage_app_public(): void
|
|
{
|
|
// Create a file in default location
|
|
$defaultPath = storage_path('app/public/test.jpg');
|
|
@mkdir(dirname($defaultPath), 0755, true);
|
|
file_put_contents($defaultPath, 'test content');
|
|
|
|
$this->artisan('offload:migrate', ['--force' => true])
|
|
->assertExitCode(0);
|
|
|
|
// Clean up
|
|
@unlink($defaultPath);
|
|
}
|
|
|
|
public function test_command_handles_empty_directory(): void
|
|
{
|
|
$emptyDir = storage_path('framework/testing/empty-dir');
|
|
@mkdir($emptyDir, 0755, true);
|
|
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $emptyDir,
|
|
'--force' => true,
|
|
])
|
|
->expectsOutput('No eligible files found.')
|
|
->assertExitCode(0);
|
|
|
|
@rmdir($emptyDir);
|
|
}
|
|
|
|
public function test_command_scans_subdirectories(): void
|
|
{
|
|
$subDir = $this->testDirectory.'/subdir';
|
|
@mkdir($subDir, 0755, true);
|
|
file_put_contents($subDir.'/nested.jpg', 'nested content');
|
|
|
|
$this->artisan('offload:migrate', [
|
|
'path' => $this->testDirectory,
|
|
'--force' => true,
|
|
])
|
|
->assertExitCode(0);
|
|
|
|
// Should find 4 files (3 in root + 1 in subdir)
|
|
$this->assertEquals(4, StorageOffloadModel::count());
|
|
}
|
|
}
|