From 832689a4e1c62b93ca420098afbb497c423d6c26 Mon Sep 17 00:00:00 2001 From: viktorprogger Date: Fri, 14 Feb 2025 04:28:40 +0500 Subject: [PATCH 1/3] Improve test coverage --- src/Exception/InvalidStatusException.php | 48 -------- src/Message/EnvelopeTrait.php | 6 +- tests/App/DummyEnvelope.php | 22 ++++ tests/App/StaticMessageHandler.php | 15 +++ tests/Unit/Command/SoftLimitTraitTest.php | 109 ++++++++++++++++++ tests/Unit/Message/EnvelopeTraitTest.php | 49 ++++++++ .../Message/JsonMessageSerializerTest.php | 50 ++++++++ tests/Unit/WorkerTest.php | 55 +++++++++ 8 files changed, 303 insertions(+), 51 deletions(-) delete mode 100644 src/Exception/InvalidStatusException.php create mode 100644 tests/App/DummyEnvelope.php create mode 100644 tests/App/StaticMessageHandler.php create mode 100644 tests/Unit/Command/SoftLimitTraitTest.php create mode 100644 tests/Unit/Message/EnvelopeTraitTest.php diff --git a/src/Exception/InvalidStatusException.php b/src/Exception/InvalidStatusException.php deleted file mode 100644 index 42d0cf31..00000000 --- a/src/Exception/InvalidStatusException.php +++ /dev/null @@ -1,48 +0,0 @@ -status = $status; - } - - public function getName(): string - { - return 'Invalid job status provided'; - } - - public function getSolution(): ?string - { - return <<status; - } -} diff --git a/src/Message/EnvelopeTrait.php b/src/Message/EnvelopeTrait.php index e8d19d65..68ae0d88 100644 --- a/src/Message/EnvelopeTrait.php +++ b/src/Message/EnvelopeTrait.php @@ -15,7 +15,7 @@ abstract public static function fromMessage(MessageInterface $message): self; public static function fromData(string $handlerName, mixed $data, array $metadata = []): MessageInterface { - return self::fromMessage(Message::fromData($handlerName, $data, $metadata)); + return static::fromMessage(Message::fromData($handlerName, $data, $metadata)); } public function getMessage(): MessageInterface @@ -46,8 +46,8 @@ public function getMetadata(): array return array_merge( $this->message->getMetadata(), [ - self::ENVELOPE_STACK_KEY => array_merge( - $this->message->getMetadata()[self::ENVELOPE_STACK_KEY] ?? [], + EnvelopeInterface::ENVELOPE_STACK_KEY => array_merge( + $this->message->getMetadata()[EnvelopeInterface::ENVELOPE_STACK_KEY] ?? [], [self::class], ), ], diff --git a/tests/App/DummyEnvelope.php b/tests/App/DummyEnvelope.php new file mode 100644 index 00000000..65c6162f --- /dev/null +++ b/tests/App/DummyEnvelope.php @@ -0,0 +1,22 @@ +message = $message; + + return $instance; + } +} diff --git a/tests/App/StaticMessageHandler.php b/tests/App/StaticMessageHandler.php new file mode 100644 index 00000000..3825836a --- /dev/null +++ b/tests/App/StaticMessageHandler.php @@ -0,0 +1,15 @@ +assertFalse($instance->memoryLimitReached()); + } + + public function testMemoryLimitNotReachedWhenUsageIsLower(): void + { + $currentMemoryUsage = memory_get_usage(true); + $instance = new class($currentMemoryUsage + 1024 * 1024) { // 1MB higher than current usage + use SoftLimitTrait { + memoryLimitReached as public; + } + + private int $limit; + + public function __construct(int $limit) + { + $this->limit = $limit; + } + + protected function getMemoryLimit(): int + { + return $this->limit; + } + }; + + $this->assertFalse($instance->memoryLimitReached()); + } + + public function testMemoryLimitReachedWhenUsageIsHigher(): void + { + $currentMemoryUsage = memory_get_usage(true); + $instance = new class($currentMemoryUsage - 1024) { // 1KB lower than current usage + use SoftLimitTrait { + memoryLimitReached as public; + } + + private int $limit; + + public function __construct(int $limit) + { + $this->limit = $limit; + } + + protected function getMemoryLimit(): int + { + return $this->limit; + } + }; + + $this->assertTrue($instance->memoryLimitReached()); + } + + public function testMemoryLimitExceededWhenUsageIncreases(): void + { + $currentMemoryUsage = memory_get_usage(true); + $instance = new class($currentMemoryUsage + 5 * 1024 * 1024) { // Set limit 5MB higher than current usage + use SoftLimitTrait { + memoryLimitReached as public; + } + + private int $limit; + + public function __construct(int $limit) + { + $this->limit = $limit; + } + + protected function getMemoryLimit(): int + { + return $this->limit; + } + }; + + // Initially memory limit is not reached + $this->assertFalse($instance->memoryLimitReached()); + + // Create a large string to increase memory usage + $largeString = str_repeat('x', 5 * 1024 * 1024 + 1); // 5MB and 1 byte string + + // Now memory limit should be exceeded + $this->assertTrue($instance->memoryLimitReached()); + + // Clean up to free memory + unset($largeString); + } +} diff --git a/tests/Unit/Message/EnvelopeTraitTest.php b/tests/Unit/Message/EnvelopeTraitTest.php new file mode 100644 index 00000000..5dd5c4a6 --- /dev/null +++ b/tests/Unit/Message/EnvelopeTraitTest.php @@ -0,0 +1,49 @@ + 'value']; + $metadata = ['meta' => 'data']; + + $envelope = DummyEnvelope::fromData($handlerName, $data, $metadata); + + $this->assertInstanceOf(DummyEnvelope::class, $envelope); + $this->assertSame($handlerName, $envelope->getHandlerName()); + $this->assertSame($data, $envelope->getData()); + $this->assertArrayHasKey('meta', $envelope->getMetadata()); + $this->assertSame('data', $envelope->getMetadata()['meta']); + } + + public function testWithMessage(): void + { + $originalMessage = new Message('original-handler', 'original-data'); + $newMessage = new Message('new-handler', 'new-data'); + + $envelope = $this->createTestEnvelope(); + $envelope = $envelope->withMessage($originalMessage); + + $this->assertSame($originalMessage, $envelope->getMessage()); + + $newEnvelope = $envelope->withMessage($newMessage); + + $this->assertNotSame($envelope, $newEnvelope); + $this->assertSame($newMessage, $newEnvelope->getMessage()); + $this->assertSame($originalMessage, $envelope->getMessage()); + } +} diff --git a/tests/Unit/Message/JsonMessageSerializerTest.php b/tests/Unit/Message/JsonMessageSerializerTest.php index 18bc5ed9..92e51301 100644 --- a/tests/Unit/Message/JsonMessageSerializerTest.php +++ b/tests/Unit/Message/JsonMessageSerializerTest.php @@ -5,6 +5,7 @@ namespace Yiisoft\Queue\Tests\Unit\Message; use InvalidArgumentException; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Yiisoft\Queue\Message\EnvelopeInterface; use Yiisoft\Queue\Message\IdEnvelope; @@ -18,6 +19,55 @@ */ final class JsonMessageSerializerTest extends TestCase { + /** + * @dataProvider dataUnsupportedHandlerNameFormat + */ + #[DataProvider('dataUnsupportedHandlerNameFormat')] + public function testHandlerNameFormat(mixed $name): void + { + $payload = ['name' => $name, 'data' => 'test']; + $serializer = $this->createSerializer(); + + $this->expectExceptionMessage(sprintf('Handler name must be a string. Got %s.', get_debug_type($name))); + $this->expectException(InvalidArgumentException::class); + $serializer->unserialize(json_encode($payload)); + } + + public static function dataUnsupportedHandlerNameFormat(): iterable + { + yield 'number' => [1]; + yield 'boolean' => [true]; + yield 'null' => [null]; + yield 'array' => [[]]; + } + + public function testDefaultMessageClassFallbackWrongClass(): void + { + $serializer = $this->createSerializer(); + $payload = [ + 'name' => 'handler', + 'data' => 'test', + 'meta' => [ + 'message-class' => 'NonExistentClass' + ] + ]; + + $message = $serializer->unserialize(json_encode($payload)); + $this->assertInstanceOf(Message::class, $message); + } + + public function testDefaultMessageClassFallbackClassNotSet(): void + { + $serializer = $this->createSerializer(); + $payload = [ + 'name' => 'handler', + 'data' => 'test', + 'meta' => [] + ]; + $message = $serializer->unserialize(json_encode($payload)); + $this->assertInstanceOf(Message::class, $message); + } + /** * @dataProvider dataUnsupportedPayloadFormat */ diff --git a/tests/Unit/WorkerTest.php b/tests/Unit/WorkerTest.php index d0fc9733..200a7262 100644 --- a/tests/Unit/WorkerTest.php +++ b/tests/Unit/WorkerTest.php @@ -18,6 +18,7 @@ use Yiisoft\Queue\Middleware\FailureHandling\MiddlewareFactoryFailureInterface; use Yiisoft\Queue\QueueInterface; use Yiisoft\Queue\Tests\App\FakeHandler; +use Yiisoft\Queue\Tests\App\StaticMessageHandler; use Yiisoft\Queue\Tests\TestCase; use Yiisoft\Queue\Worker\Worker; @@ -199,4 +200,58 @@ private function createWorkerByParams( new FailureMiddlewareDispatcher($this->createMock(MiddlewareFactoryFailureInterface::class), []), ); } + + public function testHandlerNotFoundInContainer(): void + { + $message = new Message('nonexistent', ['test-data']); + $logger = new SimpleLogger(); + $container = new SimpleContainer(); + $handlers = []; + + $queue = $this->createMock(QueueInterface::class); + $worker = $this->createWorkerByParams($handlers, $logger, $container); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Queue handler with name "nonexistent" does not exist'); + $worker->process($message, $queue); + } + + public function testHandlerInContainerNotImplementingInterface(): void + { + $message = new Message('invalid', ['test-data']); + $logger = new SimpleLogger(); + $container = new SimpleContainer([ + 'invalid' => new class() { + public function handle(): void + { + } + }, + ]); + $handlers = []; + + $queue = $this->createMock(QueueInterface::class); + $worker = $this->createWorkerByParams($handlers, $logger, $container); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Queue handler with name "invalid" does not exist'); + $worker->process($message, $queue); + } + + public function testStaticMethodHandler(): void + { + $message = new Message('static-handler', ['test-data']); + $logger = new SimpleLogger(); + $container = new SimpleContainer(); + $handlers = [ + 'static-handler' => [StaticMessageHandler::class, 'handle'], + ]; + + $queue = $this->createMock(QueueInterface::class); + $worker = $this->createWorkerByParams($handlers, $logger, $container); + + StaticMessageHandler::$wasHandled = false; + $worker->process($message, $queue); + $this->assertTrue(StaticMessageHandler::$wasHandled); + } } + From 7a0c3a23e0de53151d386f3e4a3230af3a7ef3d7 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 13 Feb 2025 23:28:55 +0000 Subject: [PATCH 2/3] Apply fixes from StyleCI --- tests/Unit/Command/SoftLimitTraitTest.php | 8 ++++---- tests/Unit/Message/JsonMessageSerializerTest.php | 6 +++--- tests/Unit/WorkerTest.php | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/Unit/Command/SoftLimitTraitTest.php b/tests/Unit/Command/SoftLimitTraitTest.php index c9944d50..6725034c 100644 --- a/tests/Unit/Command/SoftLimitTraitTest.php +++ b/tests/Unit/Command/SoftLimitTraitTest.php @@ -11,7 +11,7 @@ final class SoftLimitTraitTest extends TestCase { public function testMemoryLimitNotReachedWhenLimitIsZero(): void { - $instance = new class() { + $instance = new class () { use SoftLimitTrait { memoryLimitReached as public; } @@ -28,7 +28,7 @@ protected function getMemoryLimit(): int public function testMemoryLimitNotReachedWhenUsageIsLower(): void { $currentMemoryUsage = memory_get_usage(true); - $instance = new class($currentMemoryUsage + 1024 * 1024) { // 1MB higher than current usage + $instance = new class ($currentMemoryUsage + 1024 * 1024) { // 1MB higher than current usage use SoftLimitTrait { memoryLimitReached as public; } @@ -52,7 +52,7 @@ protected function getMemoryLimit(): int public function testMemoryLimitReachedWhenUsageIsHigher(): void { $currentMemoryUsage = memory_get_usage(true); - $instance = new class($currentMemoryUsage - 1024) { // 1KB lower than current usage + $instance = new class ($currentMemoryUsage - 1024) { // 1KB lower than current usage use SoftLimitTrait { memoryLimitReached as public; } @@ -76,7 +76,7 @@ protected function getMemoryLimit(): int public function testMemoryLimitExceededWhenUsageIncreases(): void { $currentMemoryUsage = memory_get_usage(true); - $instance = new class($currentMemoryUsage + 5 * 1024 * 1024) { // Set limit 5MB higher than current usage + $instance = new class ($currentMemoryUsage + 5 * 1024 * 1024) { // Set limit 5MB higher than current usage use SoftLimitTrait { memoryLimitReached as public; } diff --git a/tests/Unit/Message/JsonMessageSerializerTest.php b/tests/Unit/Message/JsonMessageSerializerTest.php index 92e51301..93889d3b 100644 --- a/tests/Unit/Message/JsonMessageSerializerTest.php +++ b/tests/Unit/Message/JsonMessageSerializerTest.php @@ -48,8 +48,8 @@ public function testDefaultMessageClassFallbackWrongClass(): void 'name' => 'handler', 'data' => 'test', 'meta' => [ - 'message-class' => 'NonExistentClass' - ] + 'message-class' => 'NonExistentClass', + ], ]; $message = $serializer->unserialize(json_encode($payload)); @@ -62,7 +62,7 @@ public function testDefaultMessageClassFallbackClassNotSet(): void $payload = [ 'name' => 'handler', 'data' => 'test', - 'meta' => [] + 'meta' => [], ]; $message = $serializer->unserialize(json_encode($payload)); $this->assertInstanceOf(Message::class, $message); diff --git a/tests/Unit/WorkerTest.php b/tests/Unit/WorkerTest.php index 200a7262..043ccbb7 100644 --- a/tests/Unit/WorkerTest.php +++ b/tests/Unit/WorkerTest.php @@ -221,7 +221,7 @@ public function testHandlerInContainerNotImplementingInterface(): void $message = new Message('invalid', ['test-data']); $logger = new SimpleLogger(); $container = new SimpleContainer([ - 'invalid' => new class() { + 'invalid' => new class () { public function handle(): void { } @@ -254,4 +254,3 @@ public function testStaticMethodHandler(): void $this->assertTrue(StaticMessageHandler::$wasHandled); } } - From 5e004b8d848920088fb9bac9e1dc9454947e030f Mon Sep 17 00:00:00 2001 From: viktorprogger <7670669+viktorprogger@users.noreply.github.com> Date: Thu, 13 Feb 2025 23:29:56 +0000 Subject: [PATCH 3/3] Apply Rector changes (CI) --- tests/Unit/Command/SoftLimitTraitTest.php | 15 +++------------ tests/Unit/WorkerTest.php | 2 +- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/tests/Unit/Command/SoftLimitTraitTest.php b/tests/Unit/Command/SoftLimitTraitTest.php index 6725034c..fe034a5a 100644 --- a/tests/Unit/Command/SoftLimitTraitTest.php +++ b/tests/Unit/Command/SoftLimitTraitTest.php @@ -33,11 +33,8 @@ public function testMemoryLimitNotReachedWhenUsageIsLower(): void memoryLimitReached as public; } - private int $limit; - - public function __construct(int $limit) + public function __construct(private int $limit) { - $this->limit = $limit; } protected function getMemoryLimit(): int @@ -57,11 +54,8 @@ public function testMemoryLimitReachedWhenUsageIsHigher(): void memoryLimitReached as public; } - private int $limit; - - public function __construct(int $limit) + public function __construct(private int $limit) { - $this->limit = $limit; } protected function getMemoryLimit(): int @@ -81,11 +75,8 @@ public function testMemoryLimitExceededWhenUsageIncreases(): void memoryLimitReached as public; } - private int $limit; - - public function __construct(int $limit) + public function __construct(private int $limit) { - $this->limit = $limit; } protected function getMemoryLimit(): int diff --git a/tests/Unit/WorkerTest.php b/tests/Unit/WorkerTest.php index 043ccbb7..74bbf539 100644 --- a/tests/Unit/WorkerTest.php +++ b/tests/Unit/WorkerTest.php @@ -243,7 +243,7 @@ public function testStaticMethodHandler(): void $logger = new SimpleLogger(); $container = new SimpleContainer(); $handlers = [ - 'static-handler' => [StaticMessageHandler::class, 'handle'], + 'static-handler' => StaticMessageHandler::handle(...), ]; $queue = $this->createMock(QueueInterface::class);