161 lines
4.3 KiB
PHP
161 lines
4.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Domovoy\Tests\Jobs;
|
|
|
|
use Domovoy\Models\NetworkRange;
|
|
use Domovoy\Models\ScanJob;
|
|
use Domovoy\Repositories\NetworkRangeRepository;
|
|
use Domovoy\Repositories\ScanJobRepository;
|
|
use Domovoy\Services\Discovery\NetworkScanner;
|
|
use Domovoy\Services\Jobs\ScanJobRunner;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class ScanJobRunnerTest extends TestCase
|
|
{
|
|
public function testNetworkDiscoveryJobScansItsNetworkRange(): void
|
|
{
|
|
$job = new ScanJob();
|
|
$job->id = 77;
|
|
$job->type = 'network_discovery';
|
|
$job->status = 'pending';
|
|
$job->networkRangeId = 5;
|
|
|
|
$range = new NetworkRange();
|
|
$range->id = 5;
|
|
$range->cidr = '192.168.1.1/32';
|
|
|
|
$jobs = new InMemoryScanJobRepository([$job]);
|
|
$ranges = new InMemoryNetworkRangeLookup([5 => $range]);
|
|
$scanner = new RecordingNetworkScanner();
|
|
|
|
$runner = new ScanJobRunner($jobs, $scanner, $ranges);
|
|
$runner->runNext();
|
|
|
|
self::assertSame('done', $job->status);
|
|
self::assertSame($range, $scanner->scannedRange);
|
|
self::assertSame(77, $scanner->scanJobId);
|
|
}
|
|
|
|
public function testPausedDiscoveryJobKeepsProgressAndDoesNotBecomeDone(): void
|
|
{
|
|
$job = new ScanJob();
|
|
$job->id = 88;
|
|
$job->type = 'network_discovery';
|
|
$job->status = 'pending';
|
|
$job->networkRangeId = 5;
|
|
$job->resultJson = json_encode([
|
|
'next_ip_index' => 1,
|
|
'hosts_found' => 2,
|
|
]);
|
|
|
|
$range = new NetworkRange();
|
|
$range->id = 5;
|
|
$range->cidr = '192.168.1.0/30';
|
|
|
|
$jobs = new InMemoryScanJobRepository([$job]);
|
|
$ranges = new InMemoryNetworkRangeLookup([5 => $range]);
|
|
$scanner = new RecordingNetworkScanner();
|
|
$scanner->result = [
|
|
'hosts' => [],
|
|
'completed' => false,
|
|
'next_ip_index' => 2,
|
|
'total_ips' => 2,
|
|
'scanned_count' => 1,
|
|
'hosts_found' => 2,
|
|
];
|
|
$jobs->statusAfterFirstProgressCheck = 'paused';
|
|
|
|
$runner = new ScanJobRunner($jobs, $scanner, $ranges);
|
|
$runner->runNext();
|
|
|
|
self::assertSame('paused', $job->status);
|
|
self::assertNull($job->finishedAt);
|
|
self::assertSame(1, $scanner->startIndex);
|
|
self::assertSame(2, json_decode($job->resultJson ?? '{}', true)['next_ip_index']);
|
|
}
|
|
}
|
|
|
|
final class InMemoryScanJobRepository extends ScanJobRepository
|
|
{
|
|
public ?string $statusAfterFirstProgressCheck = null;
|
|
private int $findByIdCalls = 0;
|
|
|
|
/** @param ScanJob[] $pending */
|
|
public function __construct(private array $pending)
|
|
{
|
|
}
|
|
|
|
public function findPending(): array
|
|
{
|
|
return $this->pending;
|
|
}
|
|
|
|
public function save(ScanJob $job): void
|
|
{
|
|
}
|
|
|
|
public function findById(int $id): ?ScanJob
|
|
{
|
|
$this->findByIdCalls++;
|
|
if ($this->statusAfterFirstProgressCheck !== null && $this->findByIdCalls > 1) {
|
|
$this->pending[0]->status = $this->statusAfterFirstProgressCheck;
|
|
}
|
|
return $this->pending[0] ?? null;
|
|
}
|
|
}
|
|
|
|
final class InMemoryNetworkRangeLookup extends NetworkRangeRepository
|
|
{
|
|
/** @param array<int, NetworkRange> $ranges */
|
|
public function __construct(private array $ranges)
|
|
{
|
|
}
|
|
|
|
public function findById(int $id): ?NetworkRange
|
|
{
|
|
return $this->ranges[$id] ?? null;
|
|
}
|
|
}
|
|
|
|
final class RecordingNetworkScanner extends NetworkScanner
|
|
{
|
|
public ?NetworkRange $scannedRange = null;
|
|
public ?int $scanJobId = null;
|
|
public ?int $startIndex = null;
|
|
public array $result = [
|
|
'hosts' => [],
|
|
'completed' => true,
|
|
'next_ip_index' => 1,
|
|
'total_ips' => 1,
|
|
'scanned_count' => 1,
|
|
'hosts_found' => 0,
|
|
];
|
|
|
|
public function __construct()
|
|
{
|
|
}
|
|
|
|
public function scan(NetworkRange $range, ?int $scanJobId = null): array
|
|
{
|
|
$this->scannedRange = $range;
|
|
$this->scanJobId = $scanJobId;
|
|
return [];
|
|
}
|
|
|
|
public function scanResumable(
|
|
NetworkRange $range,
|
|
int $scanJobId,
|
|
int $startIndex,
|
|
callable $shouldStop,
|
|
callable $onProgress
|
|
): array {
|
|
$this->scannedRange = $range;
|
|
$this->scanJobId = $scanJobId;
|
|
$this->startIndex = $startIndex;
|
|
$onProgress($this->result);
|
|
return $this->result;
|
|
}
|
|
}
|