chore: finish package to Blax standard (namespace, README, tests, scaffolding)
- Rename namespace BlaxSoftware\ReactPhpKernel -> Blax\ReactPhpKernel (house
standard; the BlaxSoftware\LaravelWebSockets form is grandfathered only there)
- README rewritten to the Blax OSS package principles: OSS banner, title+badges,
emoji feature list, quick start, what's-in-the-box, testing, star history
- Add PHPUnit suite (13 tests / 19 assertions, green) + phpunit.xml.dist
- Add pint.json (laravel preset, applied), composer scripts (test/lint),
.gitattributes export-ignores, test.sh (nix), CHANGELOG
- composer.json: Blax psr-4, PHP ^8.1-^8.4, dev deps
rel learn-atc #1055
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 11:24:36 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace Blax\ReactPhpKernel\Tests;
|
|
|
|
|
|
|
|
|
|
use Blax\ReactPhpKernel\Contracts\Server;
|
|
|
|
|
use Blax\ReactPhpKernel\Kernel;
|
|
|
|
|
use Blax\ReactPhpKernel\Tests\Fixtures\RecordingServer;
|
2026-07-07 11:49:43 +00:00
|
|
|
use Blax\ReactPhpKernel\Tests\Fixtures\SpyLogger;
|
chore: finish package to Blax standard (namespace, README, tests, scaffolding)
- Rename namespace BlaxSoftware\ReactPhpKernel -> Blax\ReactPhpKernel (house
standard; the BlaxSoftware\LaravelWebSockets form is grandfathered only there)
- README rewritten to the Blax OSS package principles: OSS banner, title+badges,
emoji feature list, quick start, what's-in-the-box, testing, star history
- Add PHPUnit suite (13 tests / 19 assertions, green) + phpunit.xml.dist
- Add pint.json (laravel preset, applied), composer scripts (test/lint),
.gitattributes export-ignores, test.sh (nix), CHANGELOG
- composer.json: Blax psr-4, PHP ^8.1-^8.4, dev deps
rel learn-atc #1055
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 11:24:36 +00:00
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
use React\EventLoop\LoopInterface;
|
|
|
|
|
use React\EventLoop\StreamSelectLoop;
|
|
|
|
|
|
|
|
|
|
final class KernelTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
public function test_uses_the_injected_loop(): void
|
|
|
|
|
{
|
|
|
|
|
$loop = new StreamSelectLoop;
|
|
|
|
|
|
|
|
|
|
$this->assertSame($loop, (new Kernel($loop))->loop());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_boots_and_shuts_down_registered_servers_with_hooks(): void
|
|
|
|
|
{
|
|
|
|
|
$loop = new StreamSelectLoop;
|
|
|
|
|
$kernel = new Kernel($loop);
|
|
|
|
|
|
|
|
|
|
$server = new RecordingServer;
|
|
|
|
|
// Stop the kernel on the next tick so run() returns instead of blocking.
|
|
|
|
|
$server->onBoot = fn (LoopInterface $l) => $l->futureTick(fn () => $kernel->stop());
|
|
|
|
|
|
|
|
|
|
$bootHook = false;
|
|
|
|
|
$shutdownHook = false;
|
|
|
|
|
|
|
|
|
|
$kernel
|
|
|
|
|
->register($server)
|
|
|
|
|
->onBoot(function () use (&$bootHook) {
|
|
|
|
|
$bootHook = true;
|
|
|
|
|
})
|
|
|
|
|
->onShutdown(function () use (&$shutdownHook) {
|
|
|
|
|
$shutdownHook = true;
|
|
|
|
|
})
|
|
|
|
|
->run();
|
|
|
|
|
|
|
|
|
|
$this->assertTrue($server->booted, 'server should have been booted');
|
|
|
|
|
$this->assertTrue($server->wasShutDown, 'server should have been shut down');
|
|
|
|
|
$this->assertTrue($bootHook, 'onBoot hook should have fired');
|
|
|
|
|
$this->assertTrue($shutdownHook, 'onShutdown hook should have fired');
|
|
|
|
|
$this->assertFalse($kernel->isRunning());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_stop_is_idempotent_and_safe_before_run(): void
|
|
|
|
|
{
|
|
|
|
|
$kernel = new Kernel(new StreamSelectLoop);
|
|
|
|
|
|
|
|
|
|
$kernel->stop(); // never ran — must be a harmless no-op
|
|
|
|
|
$kernel->stop();
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($kernel->isRunning());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_a_failing_server_shutdown_does_not_block_the_others(): void
|
|
|
|
|
{
|
|
|
|
|
$loop = new StreamSelectLoop;
|
|
|
|
|
$kernel = new Kernel($loop);
|
|
|
|
|
|
|
|
|
|
$throwing = new class implements Server
|
|
|
|
|
{
|
|
|
|
|
public function name(): string
|
|
|
|
|
{
|
|
|
|
|
return 'throwing';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function boot(LoopInterface $loop): void {}
|
|
|
|
|
|
|
|
|
|
public function shutdown(): void
|
|
|
|
|
{
|
|
|
|
|
throw new \RuntimeException('teardown failed');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$good = new RecordingServer;
|
|
|
|
|
$good->onBoot = fn (LoopInterface $l) => $l->futureTick(fn () => $kernel->stop());
|
|
|
|
|
|
|
|
|
|
$kernel->register($throwing)->register($good)->run();
|
|
|
|
|
|
|
|
|
|
$this->assertTrue($good->wasShutDown, 'a throwing teardown must not stop the others');
|
|
|
|
|
}
|
2026-07-07 11:49:43 +00:00
|
|
|
|
|
|
|
|
public function test_emits_lifecycle_logs_to_the_injected_logger(): void
|
|
|
|
|
{
|
|
|
|
|
$loop = new StreamSelectLoop;
|
|
|
|
|
$logger = new SpyLogger;
|
|
|
|
|
$kernel = new Kernel($loop, $logger);
|
|
|
|
|
|
|
|
|
|
$server = new RecordingServer('lifecycle');
|
|
|
|
|
$server->onBoot = fn (LoopInterface $l) => $l->futureTick(fn () => $kernel->stop());
|
|
|
|
|
|
|
|
|
|
$kernel->register($server)->run();
|
|
|
|
|
|
|
|
|
|
$this->assertSame($logger, $kernel->logger());
|
|
|
|
|
$this->assertTrue($logger->hasMessageContaining('server booted'));
|
|
|
|
|
$this->assertTrue($logger->hasMessageContaining('running'));
|
|
|
|
|
$this->assertTrue($logger->hasMessageContaining('shutting down'));
|
|
|
|
|
}
|
chore: finish package to Blax standard (namespace, README, tests, scaffolding)
- Rename namespace BlaxSoftware\ReactPhpKernel -> Blax\ReactPhpKernel (house
standard; the BlaxSoftware\LaravelWebSockets form is grandfathered only there)
- README rewritten to the Blax OSS package principles: OSS banner, title+badges,
emoji feature list, quick start, what's-in-the-box, testing, star history
- Add PHPUnit suite (13 tests / 19 assertions, green) + phpunit.xml.dist
- Add pint.json (laravel preset, applied), composer scripts (test/lint),
.gitattributes export-ignores, test.sh (nix), CHANGELOG
- composer.json: Blax psr-4, PHP ^8.1-^8.4, dev deps
rel learn-atc #1055
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 11:24:36 +00:00
|
|
|
}
|