Update README.md, consistent use of spaces instead of tabs, better examples
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Toalett\Multiprocessing\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Toalett\Multiprocessing\ConcurrencyLimit;
|
||||
use Toalett\Multiprocessing\Exception\InvalidArgumentException;
|
||||
use Toalett\Multiprocessing\Tests\Tools\PropertyInspector;
|
||||
|
||||
class ConcurrencyLimitTest extends TestCase
|
||||
{
|
||||
use PropertyInspector;
|
||||
|
||||
public function testItDoesNotAcceptZero(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Expected -1 or positive integer, got \'0\'');
|
||||
|
||||
ConcurrencyLimit::atMost(0);
|
||||
}
|
||||
|
||||
public function testItAcceptsNegativeOneAsUnlimited(): void
|
||||
{
|
||||
$limit = ConcurrencyLimit::atMost(-1);
|
||||
|
||||
self::assertTrue($limit->isUnlimited());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $negativeNumber
|
||||
* @dataProvider negativeValueProvider
|
||||
*/
|
||||
public function testItDoesNotAllowAnyOtherNegativeValue(int $negativeNumber): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage(sprintf('Expected -1 or positive integer, got \'%s\'', $negativeNumber));
|
||||
|
||||
ConcurrencyLimit::atMost($negativeNumber);
|
||||
}
|
||||
|
||||
public function testTheLimitMayBeUnlimited(): void
|
||||
{
|
||||
$limit = ConcurrencyLimit::unlimited();
|
||||
|
||||
self::assertTrue($limit->isUnlimited());
|
||||
}
|
||||
|
||||
public function testTheLimitMayBeASingleWorker(): void
|
||||
{
|
||||
$limit = ConcurrencyLimit::singleWorker();
|
||||
|
||||
self::assertFalse($limit->isUnlimited());
|
||||
self::assertEquals(1, $this->getProperty($limit, 'limit'));
|
||||
}
|
||||
|
||||
public function testAnUnlimitedLimitCanNeverBeReached(): void
|
||||
{
|
||||
$limit = ConcurrencyLimit::unlimited();
|
||||
|
||||
self::assertFalse($limit->isReachedBy(PHP_INT_MIN));
|
||||
self::assertFalse($limit->isReachedBy(0));
|
||||
self::assertFalse($limit->isReachedBy(PHP_INT_MAX));
|
||||
}
|
||||
|
||||
public function testABoundLimitCanBeReached(): void
|
||||
{
|
||||
$three = ConcurrencyLimit::atMost(3);
|
||||
$seven = ConcurrencyLimit::atMost(7);
|
||||
|
||||
self::assertTrue($three->isReachedBy(3));
|
||||
self::assertFalse($three->isReachedBy(2));
|
||||
self::assertFalse($three->isReachedBy(1));
|
||||
|
||||
self::assertTrue($seven->isReachedBy(7));
|
||||
self::assertTrue($seven->isReachedBy(120));
|
||||
self::assertFalse($seven->isReachedBy(-2));
|
||||
}
|
||||
|
||||
public function negativeValueProvider(): array
|
||||
{
|
||||
return [
|
||||
'-2' => [-2],
|
||||
'-3' => [-3],
|
||||
'-10000' => [-10000],
|
||||
'PHP_INT_MIN' => [PHP_INT_MIN],
|
||||
];
|
||||
}
|
||||
}
|
||||
87
src/Tests/ConcurrencyTest.php
Normal file
87
src/Tests/ConcurrencyTest.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Toalett\Multiprocessing\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Toalett\Multiprocessing\Concurrency;
|
||||
use Toalett\Multiprocessing\Exception\InvalidArgumentException;
|
||||
use Toalett\Multiprocessing\Tests\Tools\PropertyInspector;
|
||||
|
||||
class ConcurrencyTest extends TestCase
|
||||
{
|
||||
use PropertyInspector;
|
||||
|
||||
public function testItAcceptsNegativeOneAsUnlimited(): void
|
||||
{
|
||||
$concurrency = Concurrency::atMost(-1);
|
||||
|
||||
self::assertTrue($concurrency->isUnlimited());
|
||||
}
|
||||
|
||||
public function testItDoesNotAcceptZero(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Expected -1 or positive integer, got \'0\'');
|
||||
|
||||
Concurrency::atMost(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $negativeNumber
|
||||
* @dataProvider negativeValueProvider
|
||||
*/
|
||||
public function testItDoesNotAllowAnyOtherNegativeValue(int $negativeNumber): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage(sprintf('Expected -1 or positive integer, got \'%s\'', $negativeNumber));
|
||||
|
||||
Concurrency::atMost($negativeNumber);
|
||||
}
|
||||
|
||||
public function testTheLimitMayBeUnlimited(): void
|
||||
{
|
||||
$concurrency = Concurrency::unlimited();
|
||||
self::assertTrue($concurrency->isUnlimited());
|
||||
}
|
||||
|
||||
public function testTheLimitMayBeASingleWorker(): void
|
||||
{
|
||||
$concurrency = Concurrency::singleWorker();
|
||||
|
||||
self::assertFalse($concurrency->isUnlimited());
|
||||
self::assertEquals(1, $this->getProperty($concurrency, 'limit'));
|
||||
}
|
||||
|
||||
public function testAnUnlimitedLimitCanNeverBeReached(): void
|
||||
{
|
||||
$concurrency = Concurrency::unlimited();
|
||||
|
||||
self::assertFalse($concurrency->isReachedBy(PHP_INT_MIN));
|
||||
self::assertFalse($concurrency->isReachedBy(0));
|
||||
self::assertFalse($concurrency->isReachedBy(PHP_INT_MAX));
|
||||
}
|
||||
|
||||
public function testABoundLimitCanBeReached(): void
|
||||
{
|
||||
$three = Concurrency::atMost(3);
|
||||
$seven = Concurrency::atMost(7);
|
||||
|
||||
self::assertTrue($three->isReachedBy(3));
|
||||
self::assertFalse($three->isReachedBy(2));
|
||||
self::assertFalse($three->isReachedBy(1));
|
||||
|
||||
self::assertTrue($seven->isReachedBy(7));
|
||||
self::assertTrue($seven->isReachedBy(120));
|
||||
self::assertFalse($seven->isReachedBy(-2));
|
||||
}
|
||||
|
||||
public function negativeValueProvider(): array
|
||||
{
|
||||
return [
|
||||
'-2' => [-2],
|
||||
'-3' => [-3],
|
||||
'-10000' => [-10000],
|
||||
'PHP_INT_MIN' => [PHP_INT_MIN],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -4,77 +4,77 @@ namespace Toalett\Multiprocessing\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use Toalett\Multiprocessing\ConcurrencyLimit;
|
||||
use Toalett\Multiprocessing\Concurrency;
|
||||
use Toalett\Multiprocessing\ContextBuilder;
|
||||
use Toalett\Multiprocessing\Tests\Tools\PropertyInspector;
|
||||
use Toalett\Multiprocessing\Workers;
|
||||
|
||||
class ContextBuilderTest extends TestCase
|
||||
{
|
||||
use PropertyInspector;
|
||||
use PropertyInspector;
|
||||
|
||||
public function testItIsImmutable(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$eventLoop = $this->createMock(LoopInterface::class);
|
||||
$limit = $this->createMock(ConcurrencyLimit::class);
|
||||
public function testItIsImmutable(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$eventLoop = $this->createMock(LoopInterface::class);
|
||||
$concurrency = $this->createMock(Concurrency::class);
|
||||
|
||||
self::assertNotSame($builder->withEventLoop($eventLoop), $builder);
|
||||
self::assertNotSame($builder->withLimit($limit), $builder);
|
||||
}
|
||||
self::assertNotSame($builder->withEventLoop($eventLoop), $builder);
|
||||
self::assertNotSame($builder->withConcurrency($concurrency), $builder);
|
||||
}
|
||||
|
||||
public function testItBuildsANewContextEveryTime(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
public function testItBuildsANewContextEveryTime(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
|
||||
self::assertNotSame($builder->build(), $builder->build());
|
||||
}
|
||||
self::assertNotSame($builder->build(), $builder->build());
|
||||
}
|
||||
|
||||
public function testTheDefaultConcurrencyLimitIsUnlimited(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
public function testTheDefaultConcurrencyIsUnlimited(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
|
||||
$context = $builder->build();
|
||||
self::assertIsObject($context);
|
||||
self::assertInstanceOf(LoopInterface::class, $this->getProperty($context, 'eventLoop'));
|
||||
$context = $builder->build();
|
||||
self::assertIsObject($context);
|
||||
self::assertInstanceOf(LoopInterface::class, $this->getProperty($context, 'eventLoop'));
|
||||
|
||||
/** @var ConcurrencyLimit|null $limit */
|
||||
$limit = $this->getProperty($context, 'limit');
|
||||
self::assertIsObject($limit);
|
||||
self::assertInstanceOf(ConcurrencyLimit::class, $limit);
|
||||
self::assertTrue($limit->isUnlimited());
|
||||
}
|
||||
/** @var Concurrency|null $concurrency */
|
||||
$concurrency = $this->getProperty($context, 'concurrency');
|
||||
self::assertIsObject($concurrency);
|
||||
self::assertInstanceOf(Concurrency::class, $concurrency);
|
||||
self::assertTrue($concurrency->isUnlimited());
|
||||
}
|
||||
|
||||
public function testWhenGivenAnEventLoopItUsesThatLoop(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$eventLoop = $this->createMock(LoopInterface::class);
|
||||
public function testWhenGivenAnEventLoopItUsesThatLoop(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$eventLoop = $this->createMock(LoopInterface::class);
|
||||
|
||||
$context = $builder->withEventLoop($eventLoop)->build();
|
||||
$usedEventLoop = $this->getProperty($context, 'eventLoop');
|
||||
$context = $builder->withEventLoop($eventLoop)->build();
|
||||
$usedEventLoop = $this->getProperty($context, 'eventLoop');
|
||||
|
||||
self::assertSame($eventLoop, $usedEventLoop);
|
||||
}
|
||||
self::assertSame($eventLoop, $usedEventLoop);
|
||||
}
|
||||
|
||||
public function testWhenGivenAConcurrencyLimitItUsesThatLimit(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$limit = $this->createMock(ConcurrencyLimit::class);
|
||||
public function testWhenGivenAConcurrencyItUsesThatConcurrency(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$concurrency = $this->createMock(Concurrency::class);
|
||||
|
||||
$context = $builder->withLimit($limit)->build();
|
||||
$usedLimit = $this->getProperty($context, 'limit');
|
||||
$context = $builder->withConcurrency($concurrency)->build();
|
||||
$usedConcurrency = $this->getProperty($context, 'concurrency');
|
||||
|
||||
self::assertSame($limit, $usedLimit);
|
||||
}
|
||||
self::assertSame($concurrency, $usedConcurrency);
|
||||
}
|
||||
|
||||
public function testWhenGivenWorkersItUsesThatWorkers(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$workers = $this->createMock(Workers::class);
|
||||
public function testWhenGivenWorkersItUsesThatWorkers(): void
|
||||
{
|
||||
$builder = ContextBuilder::create();
|
||||
$workers = $this->createMock(Workers::class);
|
||||
|
||||
$context = $builder->withWorkers($workers)->build();
|
||||
$usedWorkers = $this->getProperty($context, 'workers');
|
||||
$context = $builder->withWorkers($workers)->build();
|
||||
$usedWorkers = $this->getProperty($context, 'workers');
|
||||
|
||||
self::assertSame($workers, $usedWorkers);
|
||||
}
|
||||
self::assertSame($workers, $usedWorkers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,108 +6,108 @@ use PHPUnit\Framework\TestCase;
|
||||
use React\EventLoop\Factory;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\EventLoop\Timer\Timer;
|
||||
use Toalett\Multiprocessing\ConcurrencyLimit;
|
||||
use Toalett\Multiprocessing\Concurrency;
|
||||
use Toalett\Multiprocessing\Context;
|
||||
use Toalett\Multiprocessing\Workers;
|
||||
|
||||
class ContextTest extends TestCase
|
||||
{
|
||||
public function testItEmitsAnEventWhenBooted(): void
|
||||
{
|
||||
$limit = $this->createMock(ConcurrencyLimit::class);
|
||||
$loop = Factory::create();
|
||||
$context = new Context($loop, $limit);
|
||||
public function testItEmitsAnEventWhenBooted(): void
|
||||
{
|
||||
$concurrency = $this->createMock(Concurrency::class);
|
||||
$loop = Factory::create();
|
||||
$context = new Context($loop, $concurrency);
|
||||
|
||||
$loop->futureTick(fn() => $context->stop());
|
||||
$loop->futureTick(fn() => $context->stop());
|
||||
|
||||
$bootEventHasTakenPlace = false;
|
||||
$context->on('booted', function () use (&$bootEventHasTakenPlace) {
|
||||
$bootEventHasTakenPlace = true;
|
||||
});
|
||||
$bootEventHasTakenPlace = false;
|
||||
$context->on('booted', function () use (&$bootEventHasTakenPlace) {
|
||||
$bootEventHasTakenPlace = true;
|
||||
});
|
||||
|
||||
self::assertFalse($bootEventHasTakenPlace);
|
||||
$context->run();
|
||||
self::assertTrue($bootEventHasTakenPlace);
|
||||
}
|
||||
self::assertFalse($bootEventHasTakenPlace);
|
||||
$context->run();
|
||||
self::assertTrue($bootEventHasTakenPlace);
|
||||
}
|
||||
|
||||
public function testItEmitsEventsWhenCongestionOccursAndIsRelieved(): void
|
||||
{
|
||||
$loop = Factory::create();
|
||||
$limit = $this->createMock(ConcurrencyLimit::class);
|
||||
$context = new Context($loop, $limit);
|
||||
public function testItEmitsEventsWhenCongestionOccursAndIsRelieved(): void
|
||||
{
|
||||
$loop = Factory::create();
|
||||
$concurrency = $this->createMock(Concurrency::class);
|
||||
$context = new Context($loop, $concurrency);
|
||||
|
||||
$limit->method('isReachedBy')->willReturn(true); // trigger congestion
|
||||
$concurrency->method('isReachedBy')->willReturn(true); // trigger congestion
|
||||
|
||||
$congestionEventHasTakenPlace = false;
|
||||
$context->on('congestion', function () use (&$congestionEventHasTakenPlace) {
|
||||
$congestionEventHasTakenPlace = true;
|
||||
});
|
||||
$congestionEventHasTakenPlace = false;
|
||||
$context->on('congestion', function () use (&$congestionEventHasTakenPlace) {
|
||||
$congestionEventHasTakenPlace = true;
|
||||
});
|
||||
|
||||
$congestionRelievedEventHasTakenPlace = false;
|
||||
$context->on('congestion_relieved', function () use (&$congestionRelievedEventHasTakenPlace) {
|
||||
$congestionRelievedEventHasTakenPlace = true;
|
||||
});
|
||||
$congestionRelievedEventHasTakenPlace = false;
|
||||
$context->on('congestion_relieved', function () use (&$congestionRelievedEventHasTakenPlace) {
|
||||
$congestionRelievedEventHasTakenPlace = true;
|
||||
});
|
||||
|
||||
self::assertFalse($congestionEventHasTakenPlace);
|
||||
self::assertFalse($congestionRelievedEventHasTakenPlace);
|
||||
self::assertFalse($congestionEventHasTakenPlace);
|
||||
self::assertFalse($congestionRelievedEventHasTakenPlace);
|
||||
|
||||
$loop->futureTick(fn() => $context->stop());
|
||||
$context->submit(static fn() => null);
|
||||
$context->run();
|
||||
$loop->futureTick(fn() => $context->stop());
|
||||
$context->submit(static fn() => null);
|
||||
$context->run();
|
||||
|
||||
self::assertTrue($congestionEventHasTakenPlace);
|
||||
self::assertTrue($congestionRelievedEventHasTakenPlace);
|
||||
}
|
||||
self::assertTrue($congestionEventHasTakenPlace);
|
||||
self::assertTrue($congestionRelievedEventHasTakenPlace);
|
||||
}
|
||||
|
||||
public function testItCreatesAWorkerForASubmittedTask(): void
|
||||
{
|
||||
$limit = $this->createMock(ConcurrencyLimit::class);
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$context = new Context($loop, $limit);
|
||||
public function testItCreatesAWorkerForASubmittedTask(): void
|
||||
{
|
||||
$concurrency = $this->createMock(Concurrency::class);
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$context = new Context($loop, $concurrency);
|
||||
|
||||
$limit->method('isReachedBy')->willReturn(false);
|
||||
$loop->expects(self::once())
|
||||
->method('futureTick')
|
||||
->withConsecutive([
|
||||
static fn() => null,
|
||||
]);
|
||||
$concurrency->method('isReachedBy')->willReturn(false);
|
||||
$loop->expects(self::once())
|
||||
->method('futureTick')
|
||||
->withConsecutive([
|
||||
static fn() => null,
|
||||
]);
|
||||
|
||||
$context->submit(static fn() => null);
|
||||
}
|
||||
$context->submit(static fn() => null);
|
||||
}
|
||||
|
||||
public function testItRegistersMaintenanceTasksOnTheEventLoop(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$limit = $this->createMock(ConcurrencyLimit::class);
|
||||
public function testItRegistersMaintenanceTasksOnTheEventLoop(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$concurrency = $this->createMock(Concurrency::class);
|
||||
|
||||
$loop->expects(self::exactly(2))
|
||||
->method('addPeriodicTimer')
|
||||
->withConsecutive(
|
||||
[Context::INTERVAL_CLEANUP, static fn() => null],
|
||||
[Context::INTERVAL_GC, static fn() => null]
|
||||
)->willReturnOnConsecutiveCalls(
|
||||
new Timer(Context::INTERVAL_CLEANUP, static fn() => null),
|
||||
new Timer(Context::INTERVAL_GC, static fn() => null),
|
||||
);
|
||||
$loop->expects(self::exactly(2))
|
||||
->method('addPeriodicTimer')
|
||||
->withConsecutive(
|
||||
[Context::INTERVAL_CLEANUP, static fn() => null],
|
||||
[Context::INTERVAL_GC, static fn() => null]
|
||||
)->willReturnOnConsecutiveCalls(
|
||||
new Timer(Context::INTERVAL_CLEANUP, static fn() => null),
|
||||
new Timer(Context::INTERVAL_GC, static fn() => null),
|
||||
);
|
||||
|
||||
$context = new Context($loop, $limit);
|
||||
$context->run();
|
||||
}
|
||||
$context = new Context($loop, $concurrency);
|
||||
$context->run();
|
||||
}
|
||||
|
||||
public function testItForwardsWorkersEventsToSelf(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$limit = $this->createMock(ConcurrencyLimit::class);
|
||||
$workers = $this->createMock(Workers::class);
|
||||
public function testItForwardsWorkersEventsToSelf(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$concurrency = $this->createMock(Concurrency::class);
|
||||
$workers = $this->createMock(Workers::class);
|
||||
|
||||
$workers->expects(self::exactly(3))
|
||||
->method('on')
|
||||
->withConsecutive(
|
||||
['worker_started', static fn() => null],
|
||||
['worker_stopped', static fn() => null],
|
||||
['no_workers_remaining', static fn() => null]
|
||||
);
|
||||
$workers->expects(self::exactly(3))
|
||||
->method('on')
|
||||
->withConsecutive(
|
||||
['worker_started', static fn() => null],
|
||||
['worker_stopped', static fn() => null],
|
||||
['no_workers_remaining', static fn() => null]
|
||||
);
|
||||
|
||||
new Context($loop, $limit, $workers);
|
||||
}
|
||||
new Context($loop, $concurrency, $workers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,55 +7,55 @@ use Toalett\Multiprocessing\ProcessControl\Fork;
|
||||
|
||||
class ForkTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider positiveIntegerProvider
|
||||
*/
|
||||
public function testItSaysItIsAParentProcessWhenAPositivePidIsProvided(int $pid): void
|
||||
{
|
||||
$fork = new Fork($pid);
|
||||
self::assertTrue($fork->isParent());
|
||||
self::assertFalse($fork->isChild());
|
||||
self::assertFalse($fork->failed());
|
||||
}
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider positiveIntegerProvider
|
||||
*/
|
||||
public function testItSaysItIsAParentProcessWhenAPositivePidIsProvided(int $pid): void
|
||||
{
|
||||
$fork = new Fork($pid);
|
||||
self::assertTrue($fork->isParent());
|
||||
self::assertFalse($fork->isChild());
|
||||
self::assertFalse($fork->failed());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider negativeIntegerProvider
|
||||
*/
|
||||
public function testItSaysItFailedWhenANegativePidIsProvided(int $pid): void
|
||||
{
|
||||
$fork = new Fork($pid);
|
||||
self::assertTrue($fork->isParent());
|
||||
self::assertFalse($fork->isChild());
|
||||
self::assertTrue($fork->failed());
|
||||
}
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider negativeIntegerProvider
|
||||
*/
|
||||
public function testItSaysItFailedWhenANegativePidIsProvided(int $pid): void
|
||||
{
|
||||
$fork = new Fork($pid);
|
||||
self::assertTrue($fork->isParent());
|
||||
self::assertFalse($fork->isChild());
|
||||
self::assertTrue($fork->failed());
|
||||
}
|
||||
|
||||
public function testItSaysItIsAChildProcessWhenPidZeroIsProvided(): void
|
||||
{
|
||||
$fork = new Fork(0);
|
||||
self::assertFalse($fork->isParent());
|
||||
self::assertTrue($fork->isChild());
|
||||
self::assertFalse($fork->failed());
|
||||
}
|
||||
public function testItSaysItIsAChildProcessWhenPidZeroIsProvided(): void
|
||||
{
|
||||
$fork = new Fork(0);
|
||||
self::assertFalse($fork->isParent());
|
||||
self::assertTrue($fork->isChild());
|
||||
self::assertFalse($fork->failed());
|
||||
}
|
||||
|
||||
public function positiveIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[1],
|
||||
[10],
|
||||
[1000],
|
||||
[PHP_INT_MAX],
|
||||
];
|
||||
}
|
||||
public function positiveIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[1],
|
||||
[10],
|
||||
[1000],
|
||||
[PHP_INT_MAX],
|
||||
];
|
||||
}
|
||||
|
||||
public function negativeIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[-1],
|
||||
[-10],
|
||||
[-1000],
|
||||
[PHP_INT_MIN],
|
||||
];
|
||||
}
|
||||
public function negativeIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[-1],
|
||||
[-10],
|
||||
[-1000],
|
||||
[PHP_INT_MIN],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,45 +7,45 @@ use Toalett\Multiprocessing\ProcessControl\Wait;
|
||||
|
||||
class WaitTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider positiveIntegerProvider
|
||||
*/
|
||||
public function testItSaysAChildStoppedWhenAPositivePidIsProvided(int $pid): void
|
||||
{
|
||||
$wait = new Wait($pid, 0);
|
||||
self::assertTrue($wait->childStopped());
|
||||
self::assertFalse($wait->failed());
|
||||
}
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider positiveIntegerProvider
|
||||
*/
|
||||
public function testItSaysAChildStoppedWhenAPositivePidIsProvided(int $pid): void
|
||||
{
|
||||
$wait = new Wait($pid, 0);
|
||||
self::assertTrue($wait->childStopped());
|
||||
self::assertFalse($wait->failed());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider negativeIntegerProvider
|
||||
*/
|
||||
public function testItSaysItFailedWhenANegativePidIsProvided(int $pid): void
|
||||
{
|
||||
$wait = new Wait($pid, 0);
|
||||
self::assertFalse($wait->childStopped());
|
||||
self::assertTrue($wait->failed());
|
||||
}
|
||||
/**
|
||||
* @param int $pid
|
||||
* @dataProvider negativeIntegerProvider
|
||||
*/
|
||||
public function testItSaysItFailedWhenANegativePidIsProvided(int $pid): void
|
||||
{
|
||||
$wait = new Wait($pid, 0);
|
||||
self::assertFalse($wait->childStopped());
|
||||
self::assertTrue($wait->failed());
|
||||
}
|
||||
|
||||
public function positiveIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[1],
|
||||
[10],
|
||||
[1000],
|
||||
[PHP_INT_MAX],
|
||||
];
|
||||
}
|
||||
public function positiveIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[1],
|
||||
[10],
|
||||
[1000],
|
||||
[PHP_INT_MAX],
|
||||
];
|
||||
}
|
||||
|
||||
public function negativeIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[-1],
|
||||
[-10],
|
||||
[-1000],
|
||||
[PHP_INT_MIN],
|
||||
];
|
||||
}
|
||||
public function negativeIntegerProvider(): array
|
||||
{
|
||||
return [
|
||||
[-1],
|
||||
[-10],
|
||||
[-1000],
|
||||
[PHP_INT_MIN],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,50 +9,50 @@ use Toalett\Multiprocessing\Task\Interval;
|
||||
|
||||
class IntervalTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @param $method
|
||||
* @param $val
|
||||
* @param $calculatedVal
|
||||
* @dataProvider zeroAndDownProvider
|
||||
*/
|
||||
public function testItDoesNotAllowLessThanZeroOrZero($method, $val, $calculatedVal): void
|
||||
{
|
||||
$this->setName(sprintf('It does not allow %d for %s', $val, $method));
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage(sprintf('Expected positive float, got \'%s\'', $calculatedVal));
|
||||
Interval::{$method}($val);
|
||||
}
|
||||
/**
|
||||
* @param $method
|
||||
* @param $val
|
||||
* @param $calculatedVal
|
||||
* @dataProvider zeroAndDownProvider
|
||||
*/
|
||||
public function testItDoesNotAllowLessThanZeroOrZero($method, $val, $calculatedVal): void
|
||||
{
|
||||
$this->setName(sprintf('It does not allow %d for %s', $val, $method));
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage(sprintf('Expected positive float, got \'%s\'', $calculatedVal));
|
||||
Interval::{$method}($val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $method
|
||||
* @param $val
|
||||
* @param $expected
|
||||
* @dataProvider oneAndUpProvider
|
||||
*/
|
||||
public function testItCalculatesTheCorrectInterval($method, $val, $expected): void
|
||||
{
|
||||
$this->setName('It calculates the correct interval in ' . $method);
|
||||
$interval = Interval::{$method}($val);
|
||||
/**
|
||||
* @param $method
|
||||
* @param $val
|
||||
* @param $expected
|
||||
* @dataProvider oneAndUpProvider
|
||||
*/
|
||||
public function testItCalculatesTheCorrectInterval($method, $val, $expected): void
|
||||
{
|
||||
$this->setName('It calculates the correct interval in ' . $method);
|
||||
$interval = Interval::{$method}($val);
|
||||
|
||||
self::assertEquals($expected, $interval->asFloat());
|
||||
}
|
||||
self::assertEquals($expected, $interval->asFloat());
|
||||
}
|
||||
|
||||
public function zeroAndDownProvider(): Generator
|
||||
{
|
||||
return $this->createProvider(0, -5, -9000);
|
||||
}
|
||||
public function zeroAndDownProvider(): Generator
|
||||
{
|
||||
return $this->createProvider(0, -5, -9000);
|
||||
}
|
||||
|
||||
public function oneAndUpProvider(): Generator
|
||||
{
|
||||
return $this->createProvider(1, 5, 7500);
|
||||
}
|
||||
public function oneAndUpProvider(): Generator
|
||||
{
|
||||
return $this->createProvider(1, 5, 7500);
|
||||
}
|
||||
|
||||
public function createProvider(...$args): Generator
|
||||
{
|
||||
foreach ($args as $arg) {
|
||||
yield "$arg seconds" => ['seconds', $arg, $arg];
|
||||
yield "$arg minutes" => ['minutes', $arg, $arg * 60.0];
|
||||
yield "$arg hours" => ['hours', $arg, $arg * 3600.0];
|
||||
}
|
||||
}
|
||||
public function createProvider(...$args): Generator
|
||||
{
|
||||
foreach ($args as $arg) {
|
||||
yield "$arg seconds" => ['seconds', $arg, $arg];
|
||||
yield "$arg minutes" => ['minutes', $arg, $arg * 60.0];
|
||||
yield "$arg hours" => ['hours', $arg, $arg * 3600.0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,27 +11,27 @@ use Toalett\Multiprocessing\Task\RepeatedTask;
|
||||
|
||||
class RepeatedTaskTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @param $interval
|
||||
* @dataProvider dataProvider
|
||||
*/
|
||||
public function testItRegistersWithTheProvidedInterval(Interval $interval): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$loop->expects(self::once())
|
||||
->method('addPeriodicTimer')
|
||||
->with($interval->asFloat(), static fn() => null)
|
||||
->willReturn(new Timer($interval->asFloat(), static fn() => null, true));
|
||||
/**
|
||||
* @param $interval
|
||||
* @dataProvider dataProvider
|
||||
*/
|
||||
public function testItRegistersWithTheProvidedInterval(Interval $interval): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$loop->expects(self::once())
|
||||
->method('addPeriodicTimer')
|
||||
->with($interval->asFloat(), static fn() => null)
|
||||
->willReturn(new Timer($interval->asFloat(), static fn() => null, true));
|
||||
|
||||
$task = new RepeatedTask($interval, static fn() => null);
|
||||
$task->enable($loop);
|
||||
}
|
||||
$task = new RepeatedTask($interval, static fn() => null);
|
||||
$task->enable($loop);
|
||||
}
|
||||
|
||||
public function dataProvider(): Generator
|
||||
{
|
||||
yield "3 seconds" => [Interval::seconds(3)];
|
||||
yield "5 minutes" => [Interval::minutes(5)];
|
||||
yield "half an hour" => [Interval::hours(0.5)];
|
||||
yield "a day" => [Interval::hours(24)];
|
||||
}
|
||||
public function dataProvider(): Generator
|
||||
{
|
||||
yield "3 seconds" => [Interval::seconds(3)];
|
||||
yield "5 minutes" => [Interval::minutes(5)];
|
||||
yield "half an hour" => [Interval::hours(0.5)];
|
||||
yield "a day" => [Interval::hours(24)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,89 +3,89 @@
|
||||
namespace Toalett\Multiprocessing\Tests\Task;
|
||||
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use Toalett\Multiprocessing\Task\Task;
|
||||
use Toalett\Multiprocessing\Task\Tasks;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Toalett\Multiprocessing\Tests\Tools\PropertyInspector;
|
||||
|
||||
class TasksTest extends TestCase
|
||||
{
|
||||
use PropertyInspector;
|
||||
use PropertyInspector;
|
||||
|
||||
public function testItAcceptsZeroTasks(): void
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
new Tasks();
|
||||
}
|
||||
public function testItAcceptsZeroTasks(): void
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
new Tasks();
|
||||
}
|
||||
|
||||
public function testItAcceptsMultipleTasks(): void
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
new Tasks(
|
||||
$this->createMock(Task::class),
|
||||
$this->createMock(Task::class)
|
||||
);
|
||||
}
|
||||
public function testItAcceptsMultipleTasks(): void
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
new Tasks(
|
||||
$this->createMock(Task::class),
|
||||
$this->createMock(Task::class)
|
||||
);
|
||||
}
|
||||
|
||||
public function testItDoesNotReEnableWhenEnabled(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$task = $this->createMock(Task::class);
|
||||
$tasks = new Tasks($task);
|
||||
public function testItDoesNotReEnableWhenEnabled(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$task = $this->createMock(Task::class);
|
||||
$tasks = new Tasks($task);
|
||||
|
||||
$task->expects(self::once())
|
||||
->method('enable')
|
||||
->with($loop);
|
||||
$task->expects(self::once())
|
||||
->method('enable')
|
||||
->with($loop);
|
||||
|
||||
$tasks->enable($loop);
|
||||
$tasks->enable($loop);
|
||||
}
|
||||
$tasks->enable($loop);
|
||||
$tasks->enable($loop);
|
||||
}
|
||||
|
||||
public function testItEnablesAllTasksWhenEnableCalled(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$task1 = $this->createMock(Task::class);
|
||||
$task2 = $this->createMock(Task::class);
|
||||
$task3 = $this->createMock(Task::class);
|
||||
public function testItEnablesAllTasksWhenEnableCalled(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$task1 = $this->createMock(Task::class);
|
||||
$task2 = $this->createMock(Task::class);
|
||||
$task3 = $this->createMock(Task::class);
|
||||
|
||||
foreach([$task1, $task2, $task3] as $task) {
|
||||
/** @var MockObject|Task $task */
|
||||
$task->expects(self::once())->method('enable')->with($loop);
|
||||
}
|
||||
foreach ([$task1, $task2, $task3] as $task) {
|
||||
/** @var MockObject|Task $task */
|
||||
$task->expects(self::once())->method('enable')->with($loop);
|
||||
}
|
||||
|
||||
(new Tasks($task1, $task2, $task3))->enable($loop);
|
||||
}
|
||||
(new Tasks($task1, $task2, $task3))->enable($loop);
|
||||
}
|
||||
|
||||
public function testItCancelsAllTasksWhenCancelCalled(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$task1 = $this->createMock(Task::class);
|
||||
$task2 = $this->createMock(Task::class);
|
||||
$task3 = $this->createMock(Task::class);
|
||||
public function testItCancelsAllTasksWhenCancelCalled(): void
|
||||
{
|
||||
$loop = $this->createMock(LoopInterface::class);
|
||||
$task1 = $this->createMock(Task::class);
|
||||
$task2 = $this->createMock(Task::class);
|
||||
$task3 = $this->createMock(Task::class);
|
||||
|
||||
foreach([$task1, $task2, $task3] as $task) {
|
||||
/** @var MockObject|Task $task */
|
||||
$task->expects(self::once())->method('cancel')->with($loop);
|
||||
}
|
||||
foreach ([$task1, $task2, $task3] as $task) {
|
||||
/** @var MockObject|Task $task */
|
||||
$task->expects(self::once())->method('cancel')->with($loop);
|
||||
}
|
||||
|
||||
$tasks = new Tasks($task1, $task2, $task3);
|
||||
$this->setProperty($tasks, 'loop', $loop);
|
||||
$tasks->cancel();
|
||||
}
|
||||
$tasks = new Tasks($task1, $task2, $task3);
|
||||
$this->setProperty($tasks, 'loop', $loop);
|
||||
$tasks->cancel();
|
||||
}
|
||||
|
||||
public function testItDoesNotCancelTasksWhenTheyAreNotEnabled(): void
|
||||
{
|
||||
$task1 = $this->createMock(Task::class);
|
||||
$task2 = $this->createMock(Task::class);
|
||||
$task3 = $this->createMock(Task::class);
|
||||
public function testItDoesNotCancelTasksWhenTheyAreNotEnabled(): void
|
||||
{
|
||||
$task1 = $this->createMock(Task::class);
|
||||
$task2 = $this->createMock(Task::class);
|
||||
$task3 = $this->createMock(Task::class);
|
||||
|
||||
foreach([$task1, $task2, $task3] as $task) {
|
||||
/** @var MockObject|Task $task */
|
||||
$task->expects(self::never())->method('cancel');
|
||||
}
|
||||
foreach ([$task1, $task2, $task3] as $task) {
|
||||
/** @var MockObject|Task $task */
|
||||
$task->expects(self::never())->method('cancel');
|
||||
}
|
||||
|
||||
$tasks = new Tasks($task1, $task2, $task3);
|
||||
$tasks->cancel();
|
||||
}
|
||||
$tasks = new Tasks($task1, $task2, $task3);
|
||||
$tasks->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,19 @@ use ReflectionObject;
|
||||
|
||||
trait PropertyInspector
|
||||
{
|
||||
protected function getProperty(object $object, string $propertyName)
|
||||
{
|
||||
$reflector = new ReflectionObject($object);
|
||||
$property = $reflector->getProperty($propertyName);
|
||||
$property->setAccessible(true);
|
||||
return $property->getValue($object);
|
||||
}
|
||||
protected function getProperty(object $object, string $propertyName)
|
||||
{
|
||||
$reflector = new ReflectionObject($object);
|
||||
$property = $reflector->getProperty($propertyName);
|
||||
$property->setAccessible(true);
|
||||
return $property->getValue($object);
|
||||
}
|
||||
|
||||
protected function setProperty(object $object, string $propertyName, $value): void
|
||||
{
|
||||
$reflector = new ReflectionObject($object);
|
||||
$property = $reflector->getProperty($propertyName);
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($object, $value);
|
||||
}
|
||||
protected function setProperty(object $object, string $propertyName, $value): void
|
||||
{
|
||||
$reflector = new ReflectionObject($object);
|
||||
$property = $reflector->getProperty($propertyName);
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($object, $value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,113 +11,113 @@ use Toalett\Multiprocessing\Workers;
|
||||
|
||||
class WorkersTest extends TestCase
|
||||
{
|
||||
public function testItSaysItIsEmptyWhenNoWorkers(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$workers = new Workers($processControl);
|
||||
self::assertEmpty($workers);
|
||||
}
|
||||
public function testItSaysItIsEmptyWhenNoWorkers(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$workers = new Workers($processControl);
|
||||
self::assertEmpty($workers);
|
||||
}
|
||||
|
||||
public function testItSaysItHasOneWorkerWhenTaskExecutes(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
public function testItSaysItHasOneWorkerWhenTaskExecutes(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertCount(1, $workers);
|
||||
}
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertCount(1, $workers);
|
||||
}
|
||||
|
||||
public function testItGivesTheAmountOfActiveWorkersOnCount(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
public function testItGivesTheAmountOfActiveWorkersOnCount(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertCount(2, $workers);
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertCount(2, $workers);
|
||||
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertCount(3, $workers);
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertCount(3, $workers);
|
||||
|
||||
$workers->stop();
|
||||
self::assertEmpty($workers);
|
||||
}
|
||||
$workers->stop();
|
||||
self::assertEmpty($workers);
|
||||
}
|
||||
|
||||
public function testItEmitsAnEventWhenAWorkerIsStarted(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
public function testItEmitsAnEventWhenAWorkerIsStarted(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
|
||||
$workerStartedEventHasTakenPlace = false;
|
||||
$workers->on('worker_started', function () use (&$workerStartedEventHasTakenPlace) {
|
||||
$workerStartedEventHasTakenPlace = true;
|
||||
});
|
||||
$workerStartedEventHasTakenPlace = false;
|
||||
$workers->on('worker_started', function () use (&$workerStartedEventHasTakenPlace) {
|
||||
$workerStartedEventHasTakenPlace = true;
|
||||
});
|
||||
|
||||
self::assertFalse($workerStartedEventHasTakenPlace);
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertTrue($workerStartedEventHasTakenPlace);
|
||||
}
|
||||
self::assertFalse($workerStartedEventHasTakenPlace);
|
||||
$workers->createWorkerFor(fn() => exit(0), []);
|
||||
self::assertTrue($workerStartedEventHasTakenPlace);
|
||||
}
|
||||
|
||||
public function testItEmitsAnEventWhenAWorkerIsRemoved(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
$reflector = new ReflectionObject($workers);
|
||||
$method = $reflector->getMethod('remove');
|
||||
$method->setAccessible(true);
|
||||
public function testItEmitsAnEventWhenAWorkerIsRemoved(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
$reflector = new ReflectionObject($workers);
|
||||
$method = $reflector->getMethod('remove');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$workerStoppedEventHasTakenPlace = false;
|
||||
$workers->on('worker_stopped', function () use (&$workerStoppedEventHasTakenPlace) {
|
||||
$workerStoppedEventHasTakenPlace = true;
|
||||
});
|
||||
$workerStoppedEventHasTakenPlace = false;
|
||||
$workers->on('worker_stopped', function () use (&$workerStoppedEventHasTakenPlace) {
|
||||
$workerStoppedEventHasTakenPlace = true;
|
||||
});
|
||||
|
||||
self::assertFalse($workerStoppedEventHasTakenPlace);
|
||||
$method->invoke($workers, 0);
|
||||
self::assertTrue($workerStoppedEventHasTakenPlace);
|
||||
}
|
||||
self::assertFalse($workerStoppedEventHasTakenPlace);
|
||||
$method->invoke($workers, 0);
|
||||
self::assertTrue($workerStoppedEventHasTakenPlace);
|
||||
}
|
||||
|
||||
public function testItEmitsAnEventWhenNoWorkersRemain(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
public function testItEmitsAnEventWhenNoWorkersRemain(): void
|
||||
{
|
||||
$workers = new Workers();
|
||||
|
||||
$noWorkersRemainingEventHasTakenPlace = false;
|
||||
$workers->on('no_workers_remaining', function () use (&$noWorkersRemainingEventHasTakenPlace) {
|
||||
$noWorkersRemainingEventHasTakenPlace = true;
|
||||
});
|
||||
$noWorkersRemainingEventHasTakenPlace = false;
|
||||
$workers->on('no_workers_remaining', function () use (&$noWorkersRemainingEventHasTakenPlace) {
|
||||
$noWorkersRemainingEventHasTakenPlace = true;
|
||||
});
|
||||
|
||||
self::assertFalse($noWorkersRemainingEventHasTakenPlace);
|
||||
$workers->cleanup();
|
||||
self::assertTrue($noWorkersRemainingEventHasTakenPlace);
|
||||
}
|
||||
self::assertFalse($noWorkersRemainingEventHasTakenPlace);
|
||||
$workers->cleanup();
|
||||
self::assertTrue($noWorkersRemainingEventHasTakenPlace);
|
||||
}
|
||||
|
||||
public function testItCallsForkOnProcessControlWhenAskedToCreateAWorker(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$processControl->expects(self::once())
|
||||
->method('fork')
|
||||
->willReturn(new Fork(1));
|
||||
public function testItCallsForkOnProcessControlWhenAskedToCreateAWorker(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$processControl->expects(self::once())
|
||||
->method('fork')
|
||||
->willReturn(new Fork(1));
|
||||
|
||||
$workers = new Workers($processControl);
|
||||
$workers->createWorkerFor(fn() => []);
|
||||
}
|
||||
$workers = new Workers($processControl);
|
||||
$workers->createWorkerFor(fn() => []);
|
||||
}
|
||||
|
||||
public function testItCallsNonBlockingWaitOnProcessControlWhenPerformingCleanup(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$processControl->expects(self::once())
|
||||
->method('wait')
|
||||
->with(Wait::NO_HANG)
|
||||
->willReturn(new Wait(0));
|
||||
public function testItCallsNonBlockingWaitOnProcessControlWhenPerformingCleanup(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$processControl->expects(self::once())
|
||||
->method('wait')
|
||||
->with(Wait::NO_HANG)
|
||||
->willReturn(new Wait(0));
|
||||
|
||||
$workers = new Workers($processControl);
|
||||
$workers->cleanup();
|
||||
}
|
||||
$workers = new Workers($processControl);
|
||||
$workers->cleanup();
|
||||
}
|
||||
|
||||
public function testItCallsBlockingWaitOnProcessControlWhenAwaitingCongestionRelief(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$processControl->expects(self::once())
|
||||
->method('wait')
|
||||
->with(/* no arguments */)
|
||||
->willReturn(new Wait(1));
|
||||
public function testItCallsBlockingWaitOnProcessControlWhenAwaitingCongestionRelief(): void
|
||||
{
|
||||
$processControl = $this->createMock(ProcessControl::class);
|
||||
$processControl->expects(self::once())
|
||||
->method('wait')
|
||||
->with(/* no arguments */)
|
||||
->willReturn(new Wait(1));
|
||||
|
||||
$workers = new Workers($processControl);
|
||||
$workers->awaitCongestionRelief();
|
||||
}
|
||||
$workers = new Workers($processControl);
|
||||
$workers->awaitCongestionRelief();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user