PZ build 42.x dropped the per-line `t:` (microsecond) field and tightened the spacing between `f:N`, `t:N`, and `st:N,N,N,N>` markers. The hardcoded `f:\d+,\s+t:\d+,\s+st:` requirement caused every B42 line to fail the parser's LINE regex, leaving ServerLog entries without their level/prefix and silently disabling ServerExceptionProblem and ModMissingProblem (the anchorless EngineVersionInformation still fired against the joined entry text, which is why the symptom was "one Information, no Problems"). Make `t:N,` optional via `(?:,\s+t:\d+)?` and the comma between `f:N` and `st:` optional via `,?`. The B41 format remains a strict match. Add `debug-server-42x-minimal.txt` mirroring the existing synthetic fixture in the new format, and parameterise ProjectZomboidServerLogTest with a #[DataProvider] so all four parser-shape assertions now run against both formats. Spot-check: analysers emit 3 Problems (2 exceptions, 1 missing mod) and 4 Information entries against the new fixture, identical to B41. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
3.0 KiB
PHP
84 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace IndifferentKetchup\Codex\Test\Tests\Games\ProjectZomboid\Log;
|
|
|
|
use IndifferentKetchup\Codex\Detective\Detective;
|
|
use IndifferentKetchup\Codex\Log\File\PathLogFile;
|
|
use IndifferentKetchup\Codex\Log\Level;
|
|
use IndifferentKetchup\Codex\Log\ProjectZomboid\ProjectZomboidServerLog;
|
|
use PHPUnit\Framework\Attributes\DataProvider;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class ProjectZomboidServerLogTest extends TestCase
|
|
{
|
|
/**
|
|
* Both PZ B41 and B42 line shapes must parse identically. B41 (and the
|
|
* fixture used by every analyser test) emits `f:N, t:N, st:N,N,N,N>`;
|
|
* B42 (release branch from 2026-04 onward, e.g. build 42.17) drops the
|
|
* `t:` microsecond field entirely and tightens whitespace to
|
|
* `f:N st:N,N,N,N>`.
|
|
*/
|
|
public static function fixtureProvider(): array
|
|
{
|
|
$base = __DIR__ . '/../../../../src/Games/ProjectZomboid/fixtures';
|
|
return [
|
|
'pz41-format' => [$base . '/debug-server-minimal.txt'],
|
|
'pz42-format' => [$base . '/debug-server-42x-minimal.txt'],
|
|
];
|
|
}
|
|
|
|
#[DataProvider('fixtureProvider')]
|
|
public function testParsesEntriesWithLevelAndPrefix(string $fixturePath): void
|
|
{
|
|
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($fixturePath));
|
|
$log->parse();
|
|
|
|
$entries = $log->getEntries();
|
|
$this->assertNotEmpty($entries);
|
|
|
|
$first = $entries[0];
|
|
$this->assertSame('General', $first->getPrefix());
|
|
$this->assertSame(Level::INFO, $first->getLevel());
|
|
$this->assertNotNull($first->getTime());
|
|
}
|
|
|
|
#[DataProvider('fixtureProvider')]
|
|
public function testStackTraceLinesAttachToTriggeringErrorEntry(string $fixturePath): void
|
|
{
|
|
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($fixturePath));
|
|
$log->parse();
|
|
|
|
$errorEntry = null;
|
|
foreach ($log->getEntries() as $entry) {
|
|
if ($entry->getLevel() === Level::ERROR && $entry->getPrefix() === 'General') {
|
|
$errorEntry = $entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->assertNotNull($errorEntry);
|
|
$this->assertGreaterThan(1, count($errorEntry->getLines()));
|
|
}
|
|
|
|
#[DataProvider('fixtureProvider')]
|
|
public function testWarnLevelMapsCorrectly(string $fixturePath): void
|
|
{
|
|
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($fixturePath));
|
|
$log->parse();
|
|
|
|
$warnEntries = array_filter($log->getEntries(), fn($e) => $e->getLevel() === Level::WARNING);
|
|
$this->assertNotEmpty($warnEntries);
|
|
}
|
|
|
|
#[DataProvider('fixtureProvider')]
|
|
public function testDetectiveDispatchesByContent(string $fixturePath): void
|
|
{
|
|
$detective = (new Detective())
|
|
->setLogFile(new PathLogFile($fixturePath))
|
|
->addPossibleLogClass(ProjectZomboidServerLog::class);
|
|
|
|
$log = $detective->detect();
|
|
$this->assertInstanceOf(ProjectZomboidServerLog::class, $log);
|
|
}
|
|
}
|