Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/ProcessManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class ProcessManager

private static string $input = '';

/** @var ExecutableFinder|null Finder instance for mocking in tests */
private static ?ExecutableFinder $executableFinder = null;

/** @var array Secrets to redact from error messages */
private array $secrets = [];

Expand Down Expand Up @@ -81,14 +84,24 @@ public static function setBin(string $bin): void
self::$bin = $bin;
}

/**
* Set the ExecutableFinder instance for testing.
*
* @param ExecutableFinder|null $finder The finder instance or null to use default.
*/
public static function setExecutableFinder(?ExecutableFinder $finder): void
{
self::$executableFinder = $finder;
}

public static function guessBin(): string
{
if (isset(self::$bin) && self::$bin !== '') {
return self::$bin;
}

$finder = new ExecutableFinder();
$rclonePath = $finder->find('rclone', '/usr/bin/rclone', [
$finder = self::$executableFinder ?? new ExecutableFinder();
$rclonePath = $finder->find('rclone', null, [
'/usr/local/bin',
'/usr/bin',
'/bin',
Expand Down
16 changes: 16 additions & 0 deletions tests/Unit/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,29 @@

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Process\ExecutableFinder;
use Verseles\Flyclone\CommandBuilder;
use Verseles\Flyclone\ProcessManager;
use Verseles\Flyclone\Providers\LocalProvider;
use Verseles\Flyclone\Rclone;

class ConfigurationTest extends TestCase
{
protected function setUp(): void
{
// Mock ExecutableFinder to ensure tests run even without rclone installed
$mockFinder = $this->createMock(ExecutableFinder::class);
$mockFinder->method('find')->willReturn('/mock/path/to/rclone');
ProcessManager::setExecutableFinder($mockFinder);
ProcessManager::setBin(''); // Force re-guess
}

protected function tearDown(): void
{
ProcessManager::setExecutableFinder(null);
ProcessManager::setBin('');
}

#[Test]
public function set_and_get_timeout(): void
{
Expand Down
49 changes: 49 additions & 0 deletions tests/Unit/ProcessManagerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Verseles\Flyclone\Test\Unit;

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use RuntimeException;
use Symfony\Component\Process\ExecutableFinder;
use Verseles\Flyclone\ProcessManager;

class ProcessManagerTest extends TestCase
{
protected function tearDown(): void
{
ProcessManager::setExecutableFinder(null);
ProcessManager::setBin('');
}

#[Test]
public function guess_bin_returns_path_when_found(): void
{
$mockFinder = $this->createMock(ExecutableFinder::class);
$mockFinder->method('find')
->willReturn('/usr/bin/rclone');

ProcessManager::setExecutableFinder($mockFinder);

$bin = ProcessManager::guessBin();

self::assertEquals('/usr/bin/rclone', $bin);
}

#[Test]
public function guess_bin_throws_exception_when_rclone_not_found(): void
{
$mockFinder = $this->createMock(ExecutableFinder::class);
$mockFinder->method('find')
->willReturn(null);

ProcessManager::setExecutableFinder($mockFinder);

$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Rclone binary not found');

ProcessManager::guessBin();
}
}