Files
2026-08-03 16:48:25 +02:00

117 lines
3.9 KiB
PHP

<?php
namespace Tests\Support;
use App\Services\Binaries\BinariesConfig;
use App\Services\Binaries\BinariesService;
use App\Services\Binaries\HeaderStorageService;
use App\Services\Binaries\MissedPartHandler;
class TestBinariesHarness extends BinariesService
{
public bool $failPartsInsert = false;
public ?int $failAfterFlushCount = null; // fail after N successful flushes
private int $flushCount = 0;
private array $testGroupMySQL = [];
private HeaderStorageService $testHeaderStorage;
private MissedPartHandler $testMissedPartHandler;
public function __construct()
{
// Create a minimal config that doesn't require database access
$config = new BinariesConfig(
messageBuffer: 50000,
compressedHeaders: false,
partRepair: true,
newGroupScanByDays: false,
newGroupMessagesToScan: 50000,
newGroupDaysToScan: 3,
partRepairLimit: 15000,
partRepairMaxTries: 3,
sqlChunkSize: 500,
echoCli: false
);
// Call parent with config (will still try to create NNTP, but we won't use it)
parent::__construct($config);
// Override with test-specific services
$this->testHeaderStorage = new HeaderStorageService(config: $config);
$this->testMissedPartHandler = new MissedPartHandler(
$config->partRepairLimit,
$config->partRepairMaxTries
);
}
// Expose protected method for direct testing via new service.
public function publicStoreHeaders(array $headers): void
{
if (empty($this->testGroupMySQL)) {
$this->testGroupMySQL = ['id' => 1, 'name' => 'alt.test'];
}
config(['tests.force_simulated_rollback' => false]);
// Parse headers first to add 'matches'
$parsedHeaders = [];
foreach ($headers as $header) {
if (preg_match('/^\s*(?!Usenet Index Post)(.+?)\s+\((\d+)\/(\d+)\)/', $header['Subject'], $matches)) {
if (stripos($header['Subject'], 'yEnc') === false) {
$matches[1] .= ' yEnc';
}
$header['matches'] = $matches;
$parsedHeaders[] = $header;
}
}
$this->testHeaderStorage->store($parsedHeaders, $this->testGroupMySQL, true);
}
public function setAddToPartRepair(bool $val): void
{
// This is now handled by passing parameter to store()
}
// Simulate scan path minimally to test rollback + part repair queue logic without NNTP.
public function simulateScan(array $headers, array $group, bool $enablePartRepair = true): void
{
$this->testGroupMySQL = $group;
// Parse headers first to add 'matches'
$parsedHeaders = [];
$headersReceived = [];
foreach ($headers as $header) {
if (isset($header['Number'])) {
$headersReceived[] = $header['Number'];
}
if (preg_match('/^\s*(?!Usenet Index Post)(.+?)\s+\((\d+)\/(\d+)\)/', $header['Subject'], $matches)) {
if (stripos($header['Subject'], 'yEnc') === false) {
$matches[1] .= ' yEnc';
}
$header['matches'] = $matches;
$parsedHeaders[] = $header;
}
}
// If we are simulating a failure, do not perform any inserts; just mark all as missed.
if ($this->failPartsInsert) {
if ($enablePartRepair) {
$this->testMissedPartHandler->addMissingParts(array_unique($headersReceived), $group['id']);
}
return;
}
// Normal path: process and insert.
$failedInserts = $this->testHeaderStorage->store($parsedHeaders, $group, $enablePartRepair);
if ($enablePartRepair && ! empty($failedInserts)) {
$this->testMissedPartHandler->addMissingParts($failedInserts, $group['id']);
}
}
}