2022-12-16 23:23:48 +01:00
|
|
|
<?php declare(strict_types=1);
|
2022-02-20 19:33:37 +01:00
|
|
|
|
2022-05-16 05:36:14 +02:00
|
|
|
namespace Amp\Cancellation;
|
2022-02-20 19:33:37 +01:00
|
|
|
|
2022-05-16 05:36:14 +02:00
|
|
|
use Amp\CancelledException;
|
2022-02-20 19:33:37 +01:00
|
|
|
use Amp\CompositeCancellation;
|
|
|
|
use Amp\DeferredCancellation;
|
2022-12-16 23:13:58 +01:00
|
|
|
use Amp\TestCase;
|
2022-02-20 19:33:37 +01:00
|
|
|
use function Amp\delay;
|
|
|
|
|
2022-12-16 23:13:58 +01:00
|
|
|
class CompositeCancellationTest extends TestCase
|
2022-02-20 19:33:37 +01:00
|
|
|
{
|
|
|
|
private const LOOP_COUNT = 20;
|
|
|
|
private const TOKENS_COUNT = 1000;
|
|
|
|
|
|
|
|
public function testBenchmark(): void
|
|
|
|
{
|
|
|
|
$firstMemoryMeasure = 0;
|
|
|
|
|
|
|
|
for ($i = 0; $i < self::LOOP_COUNT; $i++) {
|
|
|
|
$tokens = [];
|
|
|
|
for ($j = 0; $j < self::TOKENS_COUNT; $j++) {
|
|
|
|
$tokens[] = (new DeferredCancellation())->getCancellation();
|
|
|
|
}
|
|
|
|
$combinedToken = new CompositeCancellation(...$tokens);
|
|
|
|
|
|
|
|
if (!$firstMemoryMeasure && $i > self::LOOP_COUNT / 2) {
|
|
|
|
// Warmup and store first memory usage after 50% of iterations
|
|
|
|
$firstMemoryMeasure = \memory_get_usage(true);
|
|
|
|
}
|
|
|
|
// Remove tokens from memory
|
|
|
|
unset($combinedToken);
|
|
|
|
|
|
|
|
delay(0.001); // Tick loop to allow resources to be freed.
|
|
|
|
|
|
|
|
// Asserts
|
|
|
|
if ($firstMemoryMeasure > 0) {
|
2022-04-09 19:26:22 +02:00
|
|
|
self::assertLessThanOrEqual($firstMemoryMeasure, \memory_get_usage(true));
|
2022-02-20 19:33:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-16 05:36:14 +02:00
|
|
|
|
|
|
|
public function testCombinedWithDoubleCancellation(): void
|
|
|
|
{
|
|
|
|
$deferredCancellation1 = new DeferredCancellation();
|
|
|
|
$deferredCancellation2 = new DeferredCancellation();
|
|
|
|
|
|
|
|
$compositeCancellation = new CompositeCancellation(
|
|
|
|
$deferredCancellation1->getCancellation(),
|
|
|
|
$deferredCancellation2->getCancellation(),
|
|
|
|
);
|
|
|
|
|
|
|
|
$compositeCancellation->subscribe(
|
|
|
|
$this->createCallback(1, expectArgs: [self::isInstanceOf(CancelledException::class)])
|
|
|
|
);
|
|
|
|
|
2022-12-16 23:13:58 +01:00
|
|
|
$deferredCancellation1->cancel($exception = new \Exception());
|
|
|
|
$deferredCancellation2->cancel(new \Exception());
|
2022-05-16 05:36:14 +02:00
|
|
|
|
|
|
|
delay(0.1); // Ensure cancellation callbacks are invoked.
|
|
|
|
|
|
|
|
// Add another cancellation subscriber to ensure exception did not change.
|
|
|
|
$compositeCancellation->subscribe(function (CancelledException $cancelled) use ($exception) {
|
|
|
|
self::assertSame($exception, $cancelled->getPrevious());
|
|
|
|
});
|
2022-06-25 20:04:11 +02:00
|
|
|
|
|
|
|
delay(0.1); // Ensure cancellation callbacks are invoked.
|
|
|
|
|
|
|
|
self::assertTrue($compositeCancellation->isRequested());
|
|
|
|
|
|
|
|
$this->expectException(CancelledException::class);
|
|
|
|
|
|
|
|
$compositeCancellation->throwIfRequested();
|
2022-05-16 05:36:14 +02:00
|
|
|
}
|
2022-02-20 19:33:37 +01:00
|
|
|
}
|