2021-09-29 16:00:33 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Amp;
|
|
|
|
|
|
|
|
use Amp\PHPUnit\AsyncTestCase;
|
2021-10-15 00:50:40 +02:00
|
|
|
use Revolt\EventLoop;
|
2021-09-29 16:00:33 +02:00
|
|
|
|
2021-12-03 00:08:00 +01:00
|
|
|
class WeakClosureTest extends AsyncTestCase
|
2021-09-29 16:00:33 +02:00
|
|
|
{
|
|
|
|
public function provideObjectFactories(): iterable
|
|
|
|
{
|
2021-12-02 19:01:05 +01:00
|
|
|
yield 'binding' => [
|
2021-12-02 19:12:06 +01:00
|
|
|
fn (&$count, &$id) => new class($count, $id) {
|
2021-12-02 19:01:05 +01:00
|
|
|
private string $callbackId;
|
2021-09-29 16:00:33 +02:00
|
|
|
|
2021-12-02 19:12:06 +01:00
|
|
|
public function __construct(int &$count, &$id)
|
2021-09-29 16:00:33 +02:00
|
|
|
{
|
2021-12-02 19:12:06 +01:00
|
|
|
$this->callbackId = $id = EventLoop::repeat(
|
2021-12-02 19:01:05 +01:00
|
|
|
0.001,
|
2021-12-03 00:08:00 +01:00
|
|
|
weakClosure(function (string $callbackId) use (&$count): void {
|
2021-12-02 19:01:05 +01:00
|
|
|
AsyncTestCase::assertNotNull($this);
|
|
|
|
AsyncTestCase::assertStringContainsString('anonymous', \get_class($this));
|
|
|
|
AsyncTestCase::assertSame($callbackId, $this->callbackId);
|
|
|
|
++$count;
|
|
|
|
})
|
|
|
|
);
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function __destruct()
|
|
|
|
{
|
2021-12-02 19:01:05 +01:00
|
|
|
EventLoop::cancel($this->callbackId);
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
2021-12-02 19:01:05 +01:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
yield 'static' => [
|
2021-12-02 19:12:06 +01:00
|
|
|
fn (&$count, &$id) => new class($count, $id) {
|
2021-12-02 19:01:05 +01:00
|
|
|
private string $callbackId = '';
|
2021-09-29 16:00:33 +02:00
|
|
|
|
2021-12-02 19:12:06 +01:00
|
|
|
public function __construct(int &$count, &$id)
|
2021-09-29 16:00:33 +02:00
|
|
|
{
|
2021-12-02 19:01:05 +01:00
|
|
|
$callbackIdRef = &$this->callbackId;
|
2021-12-03 00:08:00 +01:00
|
|
|
$this->callbackId = $id = EventLoop::repeat(0.001, weakClosure(static function (string $callbackId) use (
|
2021-11-14 18:35:07 +01:00
|
|
|
&$count,
|
2021-12-02 19:01:05 +01:00
|
|
|
&$callbackIdRef
|
2021-09-29 16:00:33 +02:00
|
|
|
): void {
|
2021-12-02 19:01:05 +01:00
|
|
|
AsyncTestCase::assertSame($callbackId, $callbackIdRef);
|
2021-09-29 16:00:33 +02:00
|
|
|
++$count;
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __destruct()
|
|
|
|
{
|
2021-12-02 19:01:05 +01:00
|
|
|
EventLoop::cancel($this->callbackId);
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
2021-12-02 19:01:05 +01:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
yield 'fromCallable' => [
|
2021-12-02 19:12:06 +01:00
|
|
|
fn (&$count, &$id) => new class($count, $id) {
|
2021-12-02 19:01:05 +01:00
|
|
|
private string $callbackId = '';
|
2021-09-29 16:00:33 +02:00
|
|
|
private int $count;
|
|
|
|
|
2021-12-02 19:12:06 +01:00
|
|
|
public function __construct(int &$count, &$id)
|
2021-09-29 16:00:33 +02:00
|
|
|
{
|
|
|
|
$this->count = &$count;
|
2021-12-02 19:12:06 +01:00
|
|
|
$this->callbackId = $id = EventLoop::repeat(
|
|
|
|
0.001,
|
2021-12-03 00:08:00 +01:00
|
|
|
weakClosure(\Closure::fromCallable([$this, 'callback']))
|
2021-12-02 19:12:06 +01:00
|
|
|
);
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
|
|
|
|
2021-12-02 19:01:05 +01:00
|
|
|
private function callback(string $callbackId): void
|
2021-09-29 16:00:33 +02:00
|
|
|
{
|
|
|
|
AsyncTestCase::assertNotNull($this);
|
|
|
|
AsyncTestCase::assertStringContainsString('anonymous', \get_class($this));
|
2021-12-02 19:01:05 +01:00
|
|
|
AsyncTestCase::assertSame($callbackId, $this->callbackId);
|
2021-09-29 16:00:33 +02:00
|
|
|
++$this->count;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __destruct()
|
|
|
|
{
|
2021-12-02 19:01:05 +01:00
|
|
|
EventLoop::cancel($this->callbackId);
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
2021-12-02 19:01:05 +01:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
yield '__invoke' => [
|
2021-12-02 19:12:06 +01:00
|
|
|
fn (&$count, &$id) => new class($count, $id) {
|
2021-12-02 19:01:05 +01:00
|
|
|
private string $callbackId = '';
|
2021-09-29 16:00:33 +02:00
|
|
|
private int $count;
|
|
|
|
|
2021-12-02 19:12:06 +01:00
|
|
|
public function __construct(int &$count, &$id)
|
2021-09-29 16:00:33 +02:00
|
|
|
{
|
|
|
|
$this->count = &$count;
|
2021-12-03 00:08:00 +01:00
|
|
|
$this->callbackId = $id = EventLoop::repeat(0.001, weakClosure(\Closure::fromCallable($this)));
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
|
|
|
|
2021-12-02 19:01:05 +01:00
|
|
|
public function __invoke(string $callbackId): void
|
2021-09-29 16:00:33 +02:00
|
|
|
{
|
|
|
|
AsyncTestCase::assertNotNull($this);
|
|
|
|
AsyncTestCase::assertStringContainsString('anonymous', \get_class($this));
|
2021-12-02 19:01:05 +01:00
|
|
|
AsyncTestCase::assertSame($callbackId, $this->callbackId);
|
2021-09-29 16:00:33 +02:00
|
|
|
++$this->count;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __destruct()
|
|
|
|
{
|
2021-12-02 19:01:05 +01:00
|
|
|
EventLoop::cancel($this->callbackId);
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
2021-12-02 19:01:05 +01:00
|
|
|
},
|
2021-09-29 16:00:33 +02:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideObjectFactories
|
|
|
|
*/
|
|
|
|
public function test(callable $factory): void
|
|
|
|
{
|
2021-12-02 19:01:05 +01:00
|
|
|
$this->setTimeout(0.2);
|
2021-09-29 16:00:33 +02:00
|
|
|
$count = 0;
|
2021-12-02 19:12:06 +01:00
|
|
|
$id = null;
|
2021-09-29 16:00:33 +02:00
|
|
|
|
2021-12-02 19:12:06 +01:00
|
|
|
$object = $factory($count, $id);
|
2021-09-29 16:00:33 +02:00
|
|
|
|
2021-12-02 19:01:05 +01:00
|
|
|
delay(0.05);
|
|
|
|
self::assertGreaterThan(1, $count);
|
|
|
|
|
2021-12-02 19:12:06 +01:00
|
|
|
// Ensure the callback isn't cancelled, yet
|
|
|
|
EventLoop::enable($id);
|
2021-09-29 16:00:33 +02:00
|
|
|
|
2021-12-02 19:12:06 +01:00
|
|
|
unset($object); // Should destroy object and cancel loop watcher.
|
|
|
|
|
|
|
|
// Ensure the callback is already cancelled
|
|
|
|
$this->expectException(EventLoop\InvalidCallbackError::class);
|
|
|
|
$this->expectExceptionCode(EventLoop\InvalidCallbackError::E_INVALID_IDENTIFIER);
|
|
|
|
|
|
|
|
EventLoop::enable($id);
|
2021-09-29 16:00:33 +02:00
|
|
|
}
|
|
|
|
}
|