fix: relax DebugServerPattern::LINE for PZ B42 log format
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>
This commit is contained in:
@@ -15,7 +15,7 @@ namespace IndifferentKetchup\Codex\Pattern\ProjectZomboid;
|
|||||||
*/
|
*/
|
||||||
class DebugServerPattern
|
class DebugServerPattern
|
||||||
{
|
{
|
||||||
public const string LINE = '/^\[(\d{2}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})\]\s+(\w+)\s*:\s+(\S+)\s+f:\d+,\s+t:\d+,\s+st:[\d,]+>\s+.*$/';
|
public const string LINE = '/^\[(\d{2}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})\]\s+(\w+)\s*:\s+(\S+)\s+f:\d+(?:,\s+t:\d+)?,?\s+st:[\d,]+>\s+.*$/';
|
||||||
|
|
||||||
public const string VERSION = '/version=(?<version>\S+) (?<hash>[a-f0-9]{40}) (?<date>\d{4}-\d{2}-\d{2}) (?<time>\d{2}:\d{2}:\d{2})/';
|
public const string VERSION = '/version=(?<version>\S+) (?<hash>[a-f0-9]{40}) (?<date>\d{4}-\d{2}-\d{2}) (?<time>\d{2}:\d{2}:\d{2})/';
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[16-04-26 00:00:42.314] LOG : General f:0 st:48,648,157,434> SLF4J(W): No SLF4J providers were found..
|
||||||
|
[16-04-26 00:00:42.315] LOG : General f:0 st:48,648,157,492> SLF4J(W): Defaulting to no-operation (NOP) logger implementation.
|
||||||
|
[16-04-26 00:00:42.407] LOG : General f:0 st:48,648,157,584> version=42.17.0 0000000000000000000000000000000000000000 2026-04-20 14:34:44 (ZB) demo=false.
|
||||||
|
[16-04-26 00:00:42.407] LOG : General f:0 st:48,648,157,585> revision=0000000000000000000000000000000000000000 date=2026-04-20 time=14:34:44 (ZB).
|
||||||
|
[16-04-26 00:01:19.080] ERROR: General f:0 st:48,648,194,258> DebugFileWatcher.registerDir> Exception thrown
|
||||||
|
java.nio.file.NoSuchFileException: /placeholder/config/mods at UnixException.translateToIOException(null:-1).
|
||||||
|
Stack trace:
|
||||||
|
java.base/sun.nio.fs.UnixException.translateToIOException(Unknown Source)
|
||||||
|
java.base/sun.nio.fs.UnixException.asIOException(Unknown Source)
|
||||||
|
java.base/sun.nio.fs.LinuxWatchService$Poller.implRegister(Unknown Source)
|
||||||
|
java.base/sun.nio.fs.AbstractPoller.processRequests(Unknown Source)
|
||||||
|
java.base/sun.nio.fs.LinuxWatchService$Poller.run(Unknown Source)
|
||||||
|
[16-04-26 00:01:19.131] LOG : Mod f:0 st:48,648,194,309> loading example_mod_alpha.
|
||||||
|
[16-04-26 00:01:19.142] LOG : Mod f:0 st:48,648,194,320> loading example_mod_beta.
|
||||||
|
[16-04-26 00:01:19.155] LOG : Mod f:0 st:48,648,194,333> loading example_mod_gamma.
|
||||||
|
[16-04-26 00:01:19.200] WARN : Mod f:0 st:48,648,194,378> ZomboidFileSystem.loadModAndRequired> required mod "absent_mod" not found.
|
||||||
|
[16-04-26 00:01:45.937] ERROR: WorldGen f:0 st:48,648,221,115> IsoPropertyType.lookupOrDefaultStr> Exception thrown
|
||||||
|
zombie.core.properties.IsoPropertyType$IsoPropertyTypeNotFoundException: Property Name not found: ladderW at IsoPropertyType.lookup(IsoPropertyType.java:269). Message: Property Name not found: ladderW
|
||||||
|
at zombie.core.properties.IsoPropertyType.lookup(IsoPropertyType.java:269)
|
||||||
|
at zombie.iso.IsoChunkData.PostProcessChunk(IsoChunkData.java:512)
|
||||||
|
[16-04-26 00:02:00.000] LOG : General f:0 st:48,648,235,178> server initialised.
|
||||||
|
[16-04-26 00:05:00.000] LOG : General f:0 st:48,648,415,178> shutdown requested.
|
||||||
@@ -6,18 +6,31 @@ use IndifferentKetchup\Codex\Detective\Detective;
|
|||||||
use IndifferentKetchup\Codex\Log\File\PathLogFile;
|
use IndifferentKetchup\Codex\Log\File\PathLogFile;
|
||||||
use IndifferentKetchup\Codex\Log\Level;
|
use IndifferentKetchup\Codex\Log\Level;
|
||||||
use IndifferentKetchup\Codex\Log\ProjectZomboid\ProjectZomboidServerLog;
|
use IndifferentKetchup\Codex\Log\ProjectZomboid\ProjectZomboidServerLog;
|
||||||
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class ProjectZomboidServerLogTest extends TestCase
|
class ProjectZomboidServerLogTest extends TestCase
|
||||||
{
|
{
|
||||||
private function fixturePath(): string
|
/**
|
||||||
|
* 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
|
||||||
{
|
{
|
||||||
return __DIR__ . '/../../../../src/Games/ProjectZomboid/fixtures/debug-server-minimal.txt';
|
$base = __DIR__ . '/../../../../src/Games/ProjectZomboid/fixtures';
|
||||||
|
return [
|
||||||
|
'pz41-format' => [$base . '/debug-server-minimal.txt'],
|
||||||
|
'pz42-format' => [$base . '/debug-server-42x-minimal.txt'],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testParsesEntriesWithLevelAndPrefix(): void
|
#[DataProvider('fixtureProvider')]
|
||||||
|
public function testParsesEntriesWithLevelAndPrefix(string $fixturePath): void
|
||||||
{
|
{
|
||||||
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($this->fixturePath()));
|
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($fixturePath));
|
||||||
$log->parse();
|
$log->parse();
|
||||||
|
|
||||||
$entries = $log->getEntries();
|
$entries = $log->getEntries();
|
||||||
@@ -29,9 +42,10 @@ class ProjectZomboidServerLogTest extends TestCase
|
|||||||
$this->assertNotNull($first->getTime());
|
$this->assertNotNull($first->getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStackTraceLinesAttachToTriggeringErrorEntry(): void
|
#[DataProvider('fixtureProvider')]
|
||||||
|
public function testStackTraceLinesAttachToTriggeringErrorEntry(string $fixturePath): void
|
||||||
{
|
{
|
||||||
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($this->fixturePath()));
|
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($fixturePath));
|
||||||
$log->parse();
|
$log->parse();
|
||||||
|
|
||||||
$errorEntry = null;
|
$errorEntry = null;
|
||||||
@@ -46,19 +60,21 @@ class ProjectZomboidServerLogTest extends TestCase
|
|||||||
$this->assertGreaterThan(1, count($errorEntry->getLines()));
|
$this->assertGreaterThan(1, count($errorEntry->getLines()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWarnLevelMapsCorrectly(): void
|
#[DataProvider('fixtureProvider')]
|
||||||
|
public function testWarnLevelMapsCorrectly(string $fixturePath): void
|
||||||
{
|
{
|
||||||
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($this->fixturePath()));
|
$log = (new ProjectZomboidServerLog())->setLogFile(new PathLogFile($fixturePath));
|
||||||
$log->parse();
|
$log->parse();
|
||||||
|
|
||||||
$warnEntries = array_filter($log->getEntries(), fn($e) => $e->getLevel() === Level::WARNING);
|
$warnEntries = array_filter($log->getEntries(), fn($e) => $e->getLevel() === Level::WARNING);
|
||||||
$this->assertNotEmpty($warnEntries);
|
$this->assertNotEmpty($warnEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDetectiveDispatchesByContent(): void
|
#[DataProvider('fixtureProvider')]
|
||||||
|
public function testDetectiveDispatchesByContent(string $fixturePath): void
|
||||||
{
|
{
|
||||||
$detective = (new Detective())
|
$detective = (new Detective())
|
||||||
->setLogFile(new PathLogFile($this->fixturePath()))
|
->setLogFile(new PathLogFile($fixturePath))
|
||||||
->addPossibleLogClass(ProjectZomboidServerLog::class);
|
->addPossibleLogClass(ProjectZomboidServerLog::class);
|
||||||
|
|
||||||
$log = $detective->detect();
|
$log = $detective->detect();
|
||||||
|
|||||||
Reference in New Issue
Block a user