diff --git a/src/config/compilerpass.php b/src/DependencyInjection/WorkermanCompilerPass.php similarity index 96% rename from src/config/compilerpass.php rename to src/DependencyInjection/WorkermanCompilerPass.php index 1e910c7..e9aeb60 100644 --- a/src/config/compilerpass.php +++ b/src/DependencyInjection/WorkermanCompilerPass.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace CrazyGoat\WorkermanBundle\config; +namespace CrazyGoat\WorkermanBundle\DependencyInjection; use CrazyGoat\WorkermanBundle\Http\HttpRequestHandler; use CrazyGoat\WorkermanBundle\Http\Response\ResponseConverter; @@ -16,7 +16,8 @@ use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; -return new class implements CompilerPassInterface { +final class WorkermanCompilerPass implements CompilerPassInterface +{ public function process(ContainerBuilder $container): void { $tasks = array_map(fn(array $a) => $a[0], $container->findTaggedServiceIds('workerman.task')); @@ -89,4 +90,4 @@ private function referenceMap(array $taggedServices): array } return $result; } -}; +} diff --git a/src/WorkermanBundle.php b/src/WorkermanBundle.php index 03f9dbe..b70a2e8 100644 --- a/src/WorkermanBundle.php +++ b/src/WorkermanBundle.php @@ -4,6 +4,7 @@ namespace CrazyGoat\WorkermanBundle; +use CrazyGoat\WorkermanBundle\DependencyInjection\WorkermanCompilerPass; use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; @@ -19,7 +20,7 @@ public function configure(DefinitionConfigurator $definition): void public function build(ContainerBuilder $container): void { - $container->addCompilerPass(require __DIR__ . '/config/compilerpass.php'); + $container->addCompilerPass(new WorkermanCompilerPass()); } /** diff --git a/tests/DependencyInjection/WorkermanCompilerPassTest.php b/tests/DependencyInjection/WorkermanCompilerPassTest.php new file mode 100644 index 0000000..6518505 --- /dev/null +++ b/tests/DependencyInjection/WorkermanCompilerPassTest.php @@ -0,0 +1,157 @@ +container = new ContainerBuilder(); + $this->compilerPass = new WorkermanCompilerPass(); + } + + public function testImplementsCompilerPassInterface(): void + { + $this->assertInstanceOf(\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface::class, $this->compilerPass); + } + + public function testRegistersServiceLocatorsWhenTaggedServicesExist(): void + { + $this->container->register('workerman.config_loader', \stdClass::class); + + $this->container->register('test.task', \stdClass::class) + ->addTag('workerman.task'); + $this->container->register('test.process', \stdClass::class) + ->addTag('workerman.process'); + + $this->compilerPass->process($this->container); + + $this->assertTrue($this->container->has('workerman.task_locator')); + $this->assertTrue($this->container->has('workerman.process_locator')); + $this->assertTrue($this->container->has('workerman.reboot_strategy')); + $this->assertTrue($this->container->has('workerman.response_converter')); + $this->assertTrue($this->container->has('workerman.http_request_handler')); + $this->assertTrue($this->container->has('workerman.task_handler')); + $this->assertTrue($this->container->has('workerman.process_handler')); + } + + public function testServiceLocatorsContainCorrectReferences(): void + { + $this->container->register('workerman.config_loader', \stdClass::class); + + $this->container->register('task.service', \stdClass::class) + ->addTag('workerman.task'); + $this->container->register('process.service', \stdClass::class) + ->addTag('workerman.process'); + + $this->compilerPass->process($this->container); + + $taskLocator = $this->container->getDefinition('workerman.task_locator'); + $taskLocatorArgs = $taskLocator->getArguments(); + $this->assertArrayHasKey('task.service', $taskLocatorArgs[0]); + + $processLocator = $this->container->getDefinition('workerman.process_locator'); + $processLocatorArgs = $processLocator->getArguments(); + $this->assertArrayHasKey('process.service', $processLocatorArgs[0]); + } + + public function testHandlesNoTaggedServices(): void + { + $this->container->register('workerman.config_loader', \stdClass::class); + + $this->compilerPass->process($this->container); + + $this->assertTrue($this->container->has('workerman.task_locator')); + $this->assertTrue($this->container->has('workerman.process_locator')); + $this->assertTrue($this->container->has('workerman.reboot_strategy')); + $this->assertTrue($this->container->has('workerman.response_converter')); + } + + public function testResponseConverterStrategiesAreSortedByPriority(): void + { + $this->container->register('workerman.config_loader', \stdClass::class); + + $this->container->register('strategy.low', \stdClass::class) + ->addTag('workerman.response_converter.strategy', ['priority' => 0]); + $this->container->register('strategy.high', \stdClass::class) + ->addTag('workerman.response_converter.strategy', ['priority' => 100]); + $this->container->register('strategy.medium', \stdClass::class) + ->addTag('workerman.response_converter.strategy', ['priority' => 50]); + + $this->compilerPass->process($this->container); + + $responseConverter = $this->container->getDefinition('workerman.response_converter'); + $args = $responseConverter->getArguments(); + $references = $args[0]; + + $this->assertCount(3, $references); + $this->assertArrayHasKey('strategy.high', $references); + $this->assertArrayHasKey('strategy.medium', $references); + $this->assertArrayHasKey('strategy.low', $references); + $this->assertInstanceOf(Reference::class, $references['strategy.high']); + $this->assertInstanceOf(Reference::class, $references['strategy.medium']); + $this->assertInstanceOf(Reference::class, $references['strategy.low']); + $this->assertSame('strategy.high', (string) $references['strategy.high']); + $this->assertSame('strategy.medium', (string) $references['strategy.medium']); + $this->assertSame('strategy.low', (string) $references['strategy.low']); + } + + public function testHttpRequestHandlerIsPublic(): void + { + $this->container->register('workerman.config_loader', \stdClass::class); + + $this->compilerPass->process($this->container); + + $httpRequestHandler = $this->container->getDefinition('workerman.http_request_handler'); + $this->assertTrue($httpRequestHandler->isPublic()); + } + + public function testTaskAndProcessHandlersArePublic(): void + { + $this->container->register('workerman.config_loader', \stdClass::class); + + $this->container->register('task.service', \stdClass::class) + ->addTag('workerman.task'); + $this->container->register('process.service', \stdClass::class) + ->addTag('workerman.process'); + + $this->compilerPass->process($this->container); + + $taskHandler = $this->container->getDefinition('workerman.task_handler'); + $processHandler = $this->container->getDefinition('workerman.process_handler'); + + $this->assertTrue($taskHandler->isPublic()); + $this->assertTrue($processHandler->isPublic()); + } + + public function testReferenceMapReturnsCorrectStructure(): void + { + $this->container->register('workerman.config_loader', \stdClass::class); + + $this->container->register('service.a', \stdClass::class) + ->addTag('workerman.task'); + $this->container->register('service.b', \stdClass::class) + ->addTag('workerman.task'); + + $this->compilerPass->process($this->container); + + $taskLocator = $this->container->getDefinition('workerman.task_locator'); + $args = $taskLocator->getArguments(); + $references = $args[0]; + + $this->assertInstanceOf(Reference::class, $references['service.a']); + $this->assertInstanceOf(Reference::class, $references['service.b']); + $this->assertSame('service.a', (string) $references['service.a']); + $this->assertSame('service.b', (string) $references['service.b']); + } +}