mirror of
https://github.com/danog/amp.git
synced 2024-12-02 17:37:50 +01:00
6d5e0f5ff7
Avoids creating unnecessary promise objects. delay(0) ticking the loop only once required using delay(x) instead of delay(0) in some tests.
103 lines
2.7 KiB
PHP
103 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace Amp\Test;
|
|
|
|
use Amp\AsyncGenerator;
|
|
use Amp\CancellationToken;
|
|
use Amp\CancellationTokenSource;
|
|
use Amp\Loop;
|
|
use Amp\PHPUnit\AsyncTestCase;
|
|
use Amp\PHPUnit\TestException;
|
|
use Amp\Pipeline;
|
|
use function Amp\delay;
|
|
|
|
class CancellationTest extends AsyncTestCase
|
|
{
|
|
private function createAsyncIterator(CancellationToken $cancellationToken): Pipeline
|
|
{
|
|
return new AsyncGenerator(function () use ($cancellationToken): \Generator {
|
|
$running = true;
|
|
$cancellationToken->subscribe(function () use (&$running): void {
|
|
$running = false;
|
|
});
|
|
|
|
$i = 0;
|
|
while ($running) {
|
|
yield $i++;
|
|
}
|
|
});
|
|
}
|
|
|
|
public function testCancellationCancelsIterator(): void
|
|
{
|
|
$cancellationSource = new CancellationTokenSource;
|
|
|
|
$pipeline = $this->createAsyncIterator($cancellationSource->getToken());
|
|
|
|
$count = 0;
|
|
|
|
while (null !== $current = $pipeline->continue()) {
|
|
$count++;
|
|
|
|
$this->assertIsInt($current);
|
|
|
|
if ($current === 3) {
|
|
$cancellationSource->cancel();
|
|
}
|
|
}
|
|
|
|
$this->assertSame(4, $count);
|
|
}
|
|
|
|
public function testUnsubscribeWorks(): void
|
|
{
|
|
$cancellationSource = new CancellationTokenSource;
|
|
|
|
$id = $cancellationSource->getToken()->subscribe(function () {
|
|
$this->fail("Callback has been called");
|
|
});
|
|
|
|
$cancellationSource->getToken()->subscribe(function () {
|
|
$this->assertTrue(true);
|
|
});
|
|
|
|
$cancellationSource->getToken()->unsubscribe($id);
|
|
|
|
$cancellationSource->cancel();
|
|
}
|
|
|
|
public function testThrowingCallbacksEndUpInLoop(): void
|
|
{
|
|
Loop::setErrorHandler(function (\Throwable $exception) use (&$reason): void {
|
|
$reason = $exception;
|
|
});
|
|
|
|
$cancellationSource = new CancellationTokenSource;
|
|
$cancellationSource->getToken()->subscribe(function () {
|
|
throw new TestException;
|
|
});
|
|
|
|
$cancellationSource->cancel();
|
|
|
|
delay(1); // Tick event loop to invoke callbacks.
|
|
|
|
$this->assertInstanceOf(TestException::class, $reason);
|
|
}
|
|
|
|
public function testDoubleCancelOnlyInvokesOnce(): void
|
|
{
|
|
$cancellationSource = new CancellationTokenSource;
|
|
$cancellationSource->getToken()->subscribe($this->createCallback(1));
|
|
|
|
$cancellationSource->cancel();
|
|
$cancellationSource->cancel();
|
|
}
|
|
|
|
public function testCalledIfSubscribingAfterCancel(): void
|
|
{
|
|
$cancellationSource = new CancellationTokenSource;
|
|
$cancellationSource->cancel();
|
|
$cancellationSource->getToken()->subscribe($this->createCallback(1));
|
|
}
|
|
}
|