Skip to content

Commit

Permalink
Improve test coverage (#241)
Browse files Browse the repository at this point in the history
* Improve test coverage

* Apply fixes from StyleCI

* Apply Rector changes (CI)

---------

Co-authored-by: StyleCI Bot <[email protected]>
Co-authored-by: viktorprogger <[email protected]>
  • Loading branch information
3 people authored Feb 14, 2025
1 parent 4561dde commit a1b7171
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 51 deletions.
48 changes: 0 additions & 48 deletions src/Exception/InvalidStatusException.php

This file was deleted.

6 changes: 3 additions & 3 deletions src/Message/EnvelopeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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],
),
],
Expand Down
22 changes: 22 additions & 0 deletions tests/App/DummyEnvelope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Queue\Tests\App;

use Yiisoft\Queue\Message\EnvelopeInterface;
use Yiisoft\Queue\Message\EnvelopeTrait;
use Yiisoft\Queue\Message\MessageInterface;

final class DummyEnvelope implements EnvelopeInterface
{
use EnvelopeTrait;

public static function fromMessage(MessageInterface $message): self
{
$instance = new self();
$instance->message = $message;

return $instance;
}
}
15 changes: 15 additions & 0 deletions tests/App/StaticMessageHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Queue\Tests\App;

class StaticMessageHandler
{
public static bool $wasHandled = false;

public static function handle(): void
{
self::$wasHandled = true;
}
}
100 changes: 100 additions & 0 deletions tests/Unit/Command/SoftLimitTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Queue\Tests\Unit\Command;

use PHPUnit\Framework\TestCase;
use Yiisoft\Queue\Cli\SoftLimitTrait;

final class SoftLimitTraitTest extends TestCase
{
public function testMemoryLimitNotReachedWhenLimitIsZero(): void
{
$instance = new class () {
use SoftLimitTrait {
memoryLimitReached as public;
}

protected function getMemoryLimit(): int
{
return 0;
}
};

$this->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;
}

public function __construct(private int $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;
}

public function __construct(private int $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;
}

public function __construct(private int $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);
}
}
49 changes: 49 additions & 0 deletions tests/Unit/Message/EnvelopeTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Queue\Tests\Unit\Message;

use PHPUnit\Framework\TestCase;
use Yiisoft\Queue\Message\Message;
use Yiisoft\Queue\Tests\App\DummyEnvelope;

final class EnvelopeTraitTest extends TestCase
{
private function createTestEnvelope(): DummyEnvelope
{
return new DummyEnvelope();
}

public function testFromData(): void
{
$handlerName = 'test-handler';
$data = ['key' => '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());
}
}
50 changes: 50 additions & 0 deletions tests/Unit/Message/JsonMessageSerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
*/
Expand Down
54 changes: 54 additions & 0 deletions tests/Unit/WorkerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -199,4 +200,57 @@ 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::handle(...),
];

$queue = $this->createMock(QueueInterface::class);
$worker = $this->createWorkerByParams($handlers, $logger, $container);

StaticMessageHandler::$wasHandled = false;
$worker->process($message, $queue);
$this->assertTrue(StaticMessageHandler::$wasHandled);
}
}

0 comments on commit a1b7171

Please sign in to comment.