Skip to content

Commit 493a753

Browse files
Tests (#248)
* Add Signal Loop test * Improve WorkerTest * Apply fixes from StyleCI * Improve QueueProviderInterfaceProxyTest * Improve SignalLoopTest * Add QueueWorkerInterfaceProxyTest * Improve envelope tests * Apply fixes from StyleCI * Apply Rector changes (CI) * Improve FailureHandlingRequestTest * Add CallableFactoryTest * Apply fixes from StyleCI * Add AdapterPushHandlerTest * Fix Queue::withAdapter() return type * Update phpunit to version 12 * Fix phpunit version * Don't use phpunit 12 --------- Co-authored-by: StyleCI Bot <bot@styleci.io> Co-authored-by: viktorprogger <7670669+viktorprogger@users.noreply.github.com>
1 parent 1506bc0 commit 493a753

14 files changed

+415
-100
lines changed

src/Debug/QueueDecorator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function listen(): void
4545
$this->queue->listen();
4646
}
4747

48-
public function withAdapter(AdapterInterface $adapter): QueueInterface
48+
public function withAdapter(AdapterInterface $adapter): static
4949
{
5050
return new self($this->queue->withAdapter($adapter), $this->collector);
5151
}

src/Queue.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function status(string|int $id): JobStatus
109109
return $this->adapter->status($id);
110110
}
111111

112-
public function withAdapter(AdapterInterface $adapter): self
112+
public function withAdapter(AdapterInterface $adapter): static
113113
{
114114
$new = clone $this;
115115
$new->adapter = $adapter;

src/QueueInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function listen(): void;
4343
*/
4444
public function status(string|int $id): JobStatus;
4545

46-
public function withAdapter(AdapterInterface $adapter): self;
46+
public function withAdapter(AdapterInterface $adapter): static;
4747

4848
public function getChannel(): string;
4949
}

stubs/StubQueue.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function getAdapter(): ?AdapterInterface
4646
return $this->adapter;
4747
}
4848

49-
public function withAdapter(AdapterInterface $adapter): QueueInterface
49+
public function withAdapter(AdapterInterface $adapter): static
5050
{
5151
$new = clone $this;
5252
$new->adapter = $adapter;

tests/App/DummyQueue.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function status(string|int $id): JobStatus
3939
throw new Exception('`status()` method is not implemented yet.');
4040
}
4141

42-
public function withAdapter(AdapterInterface $adapter): QueueInterface
42+
public function withAdapter(AdapterInterface $adapter): static
4343
{
4444
throw new Exception('`withAdapter()` method is not implemented yet.');
4545
}

tests/Unit/Cli/SignalLoopTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Queue\Tests\Unit\Cli;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
10+
use Yiisoft\Queue\Cli\SignalLoop;
11+
12+
#[RequiresPhpExtension('pcntl')]
13+
final class SignalLoopTest extends TestCase
14+
{
15+
public function setUp(): void
16+
{
17+
parent::setUp();
18+
pcntl_async_signals(true);
19+
}
20+
21+
public function testMemoryLimitReached(): void
22+
{
23+
$loop = new SignalLoop(1);
24+
self::assertFalse($loop->canContinue());
25+
}
26+
27+
public function testSuspendAndResume(): void
28+
{
29+
$loop = new SignalLoop(0);
30+
pcntl_signal(\SIGALRM, static function (): void {
31+
posix_kill(getmypid(), \SIGCONT);
32+
});
33+
34+
posix_kill(getmypid(), \SIGTSTP);
35+
pcntl_alarm(1);
36+
37+
$start = microtime(true);
38+
$result = $loop->canContinue();
39+
$elapsed = microtime(true) - $start;
40+
41+
self::assertTrue($result);
42+
self::assertGreaterThan(0.5, $elapsed);
43+
}
44+
45+
#[DataProvider('exitSignalProvider')]
46+
public function testExitSignals(int $signal): void
47+
{
48+
$loop = new SignalLoop(0);
49+
50+
self::assertTrue($loop->canContinue(), 'Loop should continue');
51+
posix_kill(getmypid(), $signal);
52+
53+
self::assertFalse($loop->canContinue(), "Loop should not continue after receiving signal {$signal}");
54+
}
55+
56+
public static function exitSignalProvider(): iterable
57+
{
58+
yield 'SIGHUP' => [\SIGHUP];
59+
yield 'SIGINT' => [\SIGINT];
60+
yield 'SIGTERM' => [\SIGTERM];
61+
}
62+
63+
public function testResumeSignal(): void
64+
{
65+
$loop = new SignalLoop(0);
66+
67+
// First suspend the loop
68+
posix_kill(getmypid(), \SIGTSTP);
69+
70+
// Then immediately resume
71+
posix_kill(getmypid(), \SIGCONT);
72+
73+
$start = microtime(true);
74+
$result = $loop->canContinue();
75+
$elapsed = microtime(true) - $start;
76+
77+
self::assertTrue($result);
78+
self::assertLessThan(0.1, $elapsed, 'Loop should resume quickly without waiting');
79+
}
80+
81+
public function testMultipleExitSignals(): void
82+
{
83+
$loop = new SignalLoop(0);
84+
85+
// Send multiple exit signals
86+
posix_kill(getmypid(), \SIGINT);
87+
posix_kill(getmypid(), \SIGTERM);
88+
89+
$result = $loop->canContinue();
90+
91+
self::assertFalse($result, 'Loop should not continue after receiving any exit signal');
92+
}
93+
94+
public function testSuspendOverridesResume(): void
95+
{
96+
$loop = new SignalLoop(0);
97+
98+
// Resume first
99+
posix_kill(getmypid(), \SIGCONT);
100+
// Then suspend
101+
posix_kill(getmypid(), \SIGTSTP);
102+
103+
// Set up alarm to resume after 1 second
104+
pcntl_signal(\SIGALRM, static function (): void {
105+
posix_kill(getmypid(), \SIGCONT);
106+
});
107+
pcntl_alarm(1);
108+
109+
$start = microtime(true);
110+
$result = $loop->canContinue();
111+
$elapsed = microtime(true) - $start;
112+
113+
self::assertTrue($result);
114+
self::assertGreaterThan(0.5, $elapsed, 'Loop should wait for resume after suspend');
115+
}
116+
}

tests/Unit/Debug/QueueProviderInterfaceProxyTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,14 @@ public function testGet(): void
2323

2424
$this->assertInstanceOf(QueueDecorator::class, $factory->get('test'));
2525
}
26+
27+
public function testHas(): void
28+
{
29+
$queueFactory = $this->createMock(QueueProviderInterface::class);
30+
$queueFactory->expects($this->once())->method('has')->with('test')->willReturn(true);
31+
$collector = new QueueCollector();
32+
$factory = new QueueProviderInterfaceProxy($queueFactory, $collector);
33+
34+
$this->assertTrue($factory->has('test'));
35+
}
2636
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Queue\Tests\Unit\Debug;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Yiisoft\Queue\Debug\QueueCollector;
9+
use Yiisoft\Queue\Debug\QueueWorkerInterfaceProxy;
10+
use Yiisoft\Queue\Message\Message;
11+
use Yiisoft\Queue\Tests\App\DummyQueue;
12+
use Yiisoft\Queue\Stubs\StubWorker;
13+
14+
final class QueueWorkerInterfaceProxyTest extends TestCase
15+
{
16+
public function testProcessDelegatesToWorker(): void
17+
{
18+
$message = new Message('handler', 'data');
19+
$collector = new QueueCollector();
20+
$collector->startup();
21+
$proxy = new QueueWorkerInterfaceProxy(new StubWorker(), $collector);
22+
23+
$result = $proxy->process($message, new DummyQueue('chan'));
24+
25+
self::assertSame($message, $result);
26+
27+
$collected = $collector->getCollected();
28+
self::assertArrayHasKey('processingMessages', $collected);
29+
self::assertArrayHasKey('chan', $collected['processingMessages']);
30+
self::assertCount(1, $collected['processingMessages']['chan']);
31+
self::assertSame($message, $collected['processingMessages']['chan'][0]);
32+
}
33+
}
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
use PHPUnit\Framework\TestCase;
88
use Yiisoft\Queue\Tests\App\DummyEnvelope;
9+
use Yiisoft\Queue\Message\EnvelopeInterface;
10+
use Yiisoft\Queue\Message\Message;
911

10-
final class EnvelopeTraitTest extends TestCase
12+
final class EnvelopeTest extends TestCase
1113
{
1214
public function testFromData(): void
1315
{
@@ -23,4 +25,14 @@ public function testFromData(): void
2325
$this->assertArrayHasKey('meta', $envelope->getMetadata());
2426
$this->assertSame('data', $envelope->getMetadata()['meta']);
2527
}
28+
29+
public function testNonArrayStackIsNormalized(): void
30+
{
31+
$base = new Message('handler', 'data', [EnvelopeInterface::ENVELOPE_STACK_KEY => 'oops']);
32+
$wrapped = new DummyEnvelope($base, 'id-1');
33+
34+
$meta = $wrapped->getMetadata();
35+
self::assertIsArray($meta[EnvelopeInterface::ENVELOPE_STACK_KEY]);
36+
self::assertSame([DummyEnvelope::class], $meta[EnvelopeInterface::ENVELOPE_STACK_KEY]);
37+
}
2638
}

tests/Unit/Message/JsonMessageSerializerTest.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ public function testDefaultMessageClassFallbackClassNotSet(): void
6767
$this->assertInstanceOf(Message::class, $message);
6868
}
6969

70-
/**
71-
* @dataProvider dataUnsupportedPayloadFormat
72-
*/
70+
#[DataProvider('dataUnsupportedPayloadFormat')]
7371
public function testPayloadFormat(mixed $payload): void
7472
{
7573
$serializer = $this->createSerializer();
@@ -87,9 +85,7 @@ public static function dataUnsupportedPayloadFormat(): iterable
8785
yield 'null' => [null];
8886
}
8987

90-
/**
91-
* @dataProvider dataUnsupportedMetadataFormat
92-
*/
88+
#[DataProvider('dataUnsupportedMetadataFormat')]
9389
public function testMetadataFormat(mixed $meta): void
9490
{
9591
$payload = ['name' => 'handler', 'data' => 'test', 'meta' => $meta];
@@ -142,6 +138,7 @@ public function testUnserializeEnvelopeStack(): void
142138
];
143139
$serializer = $this->createSerializer();
144140

141+
/** @var IdEnvelope $message */
145142
$message = $serializer->unserialize(json_encode($payload));
146143

147144
$this->assertEquals($payload['data'], $message->getData());
@@ -185,6 +182,7 @@ public function testSerializeEnvelopeStack(): void
185182
$json,
186183
);
187184

185+
/** @var IdEnvelope $message */
188186
$message = $serializer->unserialize($json);
189187

190188
$this->assertInstanceOf(IdEnvelope::class, $message);

0 commit comments

Comments
 (0)