From 423c6d3963f2c62060c9162630d75a9fc85f313d Mon Sep 17 00:00:00 2001 From: indifferentketchup Date: Thu, 30 Apr 2026 21:33:07 +0000 Subject: [PATCH] Add ServerExceptionProblem insight --- .../ProjectZomboid/ServerExceptionProblem.php | 46 ++++++++++++++ .../ProjectZomboid/DebugServerPattern.php | 2 + .../Analysis/ServerExceptionProblemTest.php | 62 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 src/Analysis/ProjectZomboid/ServerExceptionProblem.php create mode 100644 test/tests/Games/ProjectZomboid/Analysis/ServerExceptionProblemTest.php diff --git a/src/Analysis/ProjectZomboid/ServerExceptionProblem.php b/src/Analysis/ProjectZomboid/ServerExceptionProblem.php new file mode 100644 index 0000000..a23c529 --- /dev/null +++ b/src/Analysis/ProjectZomboid/ServerExceptionProblem.php @@ -0,0 +1,46 @@ +exceptionType = $matches['type']; + $this->body = trim($matches['body'] ?? ''); + } + + public function getExceptionType(): string + { + return $this->exceptionType; + } + + public function getBody(): string + { + return $this->body; + } + + public function getMessage(): string + { + return sprintf('Exception thrown: %s', $this->exceptionType); + } + + public function isEqual(InsightInterface $insight): bool + { + return $insight instanceof self + && $insight->getExceptionType() === $this->exceptionType; + } +} diff --git a/src/Pattern/ProjectZomboid/DebugServerPattern.php b/src/Pattern/ProjectZomboid/DebugServerPattern.php index c58c00f..bf9c95c 100644 --- a/src/Pattern/ProjectZomboid/DebugServerPattern.php +++ b/src/Pattern/ProjectZomboid/DebugServerPattern.php @@ -24,4 +24,6 @@ class DebugServerPattern public const string MOD_MISSING = '/required mod "(?[^"]+)" not found/'; public const string EXCEPTION_HEADER = '/^\[\d{2}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\]\s+ERROR:.*Exception thrown/'; + + public const string EXCEPTION = '/^\[\d{2}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\][^\n]+Exception thrown\n\t(?[A-Za-z0-9_.$]+(?:Exception|Error))[^\n]*(?(?:\n\t.+)*)/'; } diff --git a/test/tests/Games/ProjectZomboid/Analysis/ServerExceptionProblemTest.php b/test/tests/Games/ProjectZomboid/Analysis/ServerExceptionProblemTest.php new file mode 100644 index 0000000..fca25eb --- /dev/null +++ b/test/tests/Games/ProjectZomboid/Analysis/ServerExceptionProblemTest.php @@ -0,0 +1,62 @@ +assertSame([DebugServerPattern::EXCEPTION], ServerExceptionProblem::getPatterns()); + } + + public function testSetMatchesCapturesTypeAndBodyAcrossLines(): void + { + $entryText = "[16-04-26 00:01:19.080] ERROR: General f:0, t:1776297679080, st:48,648,194,258> DebugFileWatcher.registerDir> Exception thrown\n" + . "\tjava.nio.file.NoSuchFileException: /placeholder/config/mods at UnixException.translateToIOException(null:-1).\n" + . "\tStack trace:\n" + . "\t\tjava.base/sun.nio.fs.UnixException.translateToIOException(Unknown Source)"; + + $this->assertSame(1, preg_match(DebugServerPattern::EXCEPTION, $entryText, $matches)); + + $problem = new ServerExceptionProblem(); + $problem->setMatches($matches, 0); + + $this->assertSame('java.nio.file.NoSuchFileException', $problem->getExceptionType()); + $this->assertStringContainsString('Stack trace', $problem->getBody()); + $this->assertStringContainsString('java.base/sun.nio.fs.UnixException', $problem->getBody()); + } + + public function testIsEqualCoalescesSameTypeRegardlessOfBody(): void + { + $a = $this->problemFor('java.io.IOException', 'body one'); + $b = $this->problemFor('java.io.IOException', 'body two completely different'); + $c = $this->problemFor('java.lang.RuntimeException', 'body one'); + + $this->assertTrue($a->isEqual($b)); + $this->assertFalse($a->isEqual($c)); + } + + public function testNestedExceptionTypeNamesAreSupported(): void + { + $entryText = "[16-04-26 00:01:45.937] ERROR: WorldGen f:0, t:1776297705937, st:48,648,221,115> IsoPropertyType.lookupOrDefaultStr> Exception thrown\n" + . "\tzombie.core.properties.IsoPropertyType\$IsoPropertyTypeNotFoundException: Property Name not found: ladderW"; + + $this->assertSame(1, preg_match(DebugServerPattern::EXCEPTION, $entryText, $matches)); + + $problem = new ServerExceptionProblem(); + $problem->setMatches($matches, 0); + + $this->assertSame('zombie.core.properties.IsoPropertyType$IsoPropertyTypeNotFoundException', $problem->getExceptionType()); + } + + private function problemFor(string $type, string $body): ServerExceptionProblem + { + $problem = new ServerExceptionProblem(); + $problem->setMatches(['type' => $type, 'body' => $body], 0); + return $problem; + } +}