From b89c615d7ea709515ac467076e146943707ecf98 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 12 May 2017 14:33:50 +0300 Subject: [PATCH 1/5] [amqp] Configure by string DSN. --- docs/bundle/config_reference.md | 12 +- docs/bundle/quick_tour.md | 7 +- docs/client/quick_tour.md | 8 +- docs/quick_tour.md | 4 +- docs/transport/amqp.md | 21 ++- pkg/amqp-ext/AmqpConnectionFactory.php | 108 +++++++++-- pkg/amqp-ext/Symfony/AmqpTransportFactory.php | 17 +- .../Tests/AmqpConnectionFactoryConfigTest.php | 167 ++++++++++++++++++ .../Tests/AmqpConnectionFactoryTest.php | 36 ---- .../Symfony/AmqpTransportFactoryTest.php | 60 ++++++- .../RabbitMqAmqpTransportFactoryTest.php | 16 +- pkg/amqp-ext/examples/consume.php | 4 +- pkg/amqp-ext/examples/produce.php | 4 +- .../Tests/Functional/RpcClientTest.php | 1 - .../Tests/Functional/UseCasesTest.php | 4 +- .../Tests/Functional/Client/RpcClientTest.php | 4 +- .../Tests/Functional/SimpleClientTest.php | 8 +- pkg/test/RabbitmqAmqpExtension.php | 4 +- 18 files changed, 371 insertions(+), 114 deletions(-) create mode 100644 pkg/amqp-ext/Tests/AmqpConnectionFactoryConfigTest.php diff --git a/docs/bundle/config_reference.md b/docs/bundle/config_reference.md index 48d01b645..6b62ba709 100644 --- a/docs/bundle/config_reference.md +++ b/docs/bundle/config_reference.md @@ -43,11 +43,11 @@ enqueue: # Port on the host. port: 5672 - # The login name to use. Note: Max 128 characters. - login: guest + # The user name to use. Note: Max 128 characters. + user: guest # Password. Note: Max 128 characters. - password: guest + pass: guest # The virtual host on the host. Note: Max 128 characters. vhost: / @@ -70,11 +70,11 @@ enqueue: # Port on the host. port: 5672 - # The login name to use. Note: Max 128 characters. - login: guest + # The user name to use. Note: Max 128 characters. + user: guest # Password. Note: Max 128 characters. - password: guest + pass: guest # The virtual host on the host. Note: Max 128 characters. vhost: / diff --git a/docs/bundle/quick_tour.md b/docs/bundle/quick_tour.md index 95eac7fdd..b05e46cd7 100644 --- a/docs/bundle/quick_tour.md +++ b/docs/bundle/quick_tour.md @@ -46,12 +46,7 @@ First, you have to configure a transport layer and set one to be default. enqueue: transport: default: 'amqp' - amqp: - host: 'localhost' - port: 5672 - login: 'guest' - password: 'guest' - vhost: '/' + amqp: "amqp://" client: ~ ``` diff --git a/docs/client/quick_tour.md b/docs/client/quick_tour.md index 107f2bbaa..3cca27de2 100644 --- a/docs/client/quick_tour.md +++ b/docs/client/quick_tour.md @@ -25,13 +25,7 @@ include __DIR__.'/vendor/autoload.php'; $client = new SimpleClient([ 'transport' => [ 'default' => 'amqp', - 'amqp' => [ - 'host' => 'localhost', - 'port' => 5672, - 'vhost' => '/', - 'login' => 'guest', - 'password' => 'guest', - ], + 'amqp' => 'amqp://' ], 'client' => [ 'app_name' => 'plain_php', diff --git a/docs/quick_tour.md b/docs/quick_tour.md index d7749b73a..1c32a73ef 100644 --- a/docs/quick_tour.md +++ b/docs/quick_tour.md @@ -177,8 +177,8 @@ $client = new SimpleClient([ 'host' => 'localhost', 'port' => 5672, 'vhost' => '/', - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', ], ], 'client' => true, diff --git a/docs/transport/amqp.md b/docs/transport/amqp.md index a1573ce82..ebab8a093 100644 --- a/docs/transport/amqp.md +++ b/docs/transport/amqp.md @@ -25,15 +25,28 @@ $ composer require enqueue/amqp-ext '127.0.0.1', - 'port' => 5672, + 'host' => 'example.com', + 'port' => 1000, 'vhost' => '/', - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'user', + 'pass' => 'pass', 'persisted' => false, ]); +// same as above but given as DSN string +$connectionFactory = new AmqpConnectionFactory('amqp://user:pass:10000@example.com/%2f'); + $psrContext = $connectionFactory->createContext(); ``` diff --git a/pkg/amqp-ext/AmqpConnectionFactory.php b/pkg/amqp-ext/AmqpConnectionFactory.php index 4cd75ac62..e168cf796 100644 --- a/pkg/amqp-ext/AmqpConnectionFactory.php +++ b/pkg/amqp-ext/AmqpConnectionFactory.php @@ -17,35 +17,39 @@ class AmqpConnectionFactory implements PsrConnectionFactory private $connection; /** - * $config = [ + * The config could be an array, string DSN or null. In case of null it will attempt to connect to localhost with default credentials + * + * [ * 'host' => amqp.host The host to connect too. Note: Max 1024 characters. * 'port' => amqp.port Port on the host. * 'vhost' => amqp.vhost The virtual host on the host. Note: Max 128 characters. - * 'login' => amqp.login The login name to use. Note: Max 128 characters. - * 'password' => amqp.password Password. Note: Max 128 characters. + * 'user' => amqp.user The user name to use. Note: Max 128 characters. + * 'pass' => amqp.password Password. Note: Max 128 characters. * 'read_timeout' => Timeout in for income activity. Note: 0 or greater seconds. May be fractional. * 'write_timeout' => Timeout in for outcome activity. Note: 0 or greater seconds. May be fractional. * 'connect_timeout' => Connection timeout. Note: 0 or greater seconds. May be fractional. * 'persisted' => bool, Whether it use single persisted connection or open a new one for every context * 'lazy' => the connection will be performed as later as possible, if the option set to true - * ]. + * ] + * + * or + * + * amqp://user:pass@host:10000/vhost?lazy=true&persisted=false&read_timeout=2 * - * @param $config + * @param array|string $config */ - public function __construct(array $config) + public function __construct($config = 'amqp://') { - $this->config = array_replace([ - 'host' => null, - 'port' => null, - 'vhost' => null, - 'login' => null, - 'password' => null, - 'read_timeout' => null, - 'write_timeout' => null, - 'connect_timeout' => null, - 'persisted' => false, - 'lazy' => true, - ], $config); + if (empty($config)) { + $config = []; + } else if (is_string($config)) { + $config = $this->parseDsn($config); + } else if (is_array($config)) { + } else { + throw new \LogicException('The config must be eaither an array of options, a DSN string or null'); + } + + $this->config = array_replace($this->defaultConfig(), $config); } /** @@ -78,4 +82,72 @@ private function establishConnection() return $this->connection; } + + /** + * @param string $dsn + * + * @return array + */ + private function parseDsn($dsn) + { + if ('amqp://' == $dsn) { + return []; + } + + $dsnConfig = parse_url($dsn); + if (false === $dsnConfig) { + throw new \LogicException(sprintf('Failed to parse DSN "%s"', $dsn)); + } + + $dsnConfig = array_replace([ + 'scheme' => null, + 'host' => null, + 'port' => null, + 'user' => null, + 'pass' => null, + 'path' => null, + 'query' => null, + ], $dsnConfig); + + if ('amqp' !== $dsnConfig['scheme']) { + throw new \LogicException('The given DSN scheme "%s" is not supported. Could be "amqp" only.'); + } + + if ($dsnConfig['query']) { + $query = []; + parse_str($dsnConfig['query'], $query); + $dsnConfig = array_replace($query, $dsnConfig); + } + + $dsnConfig['vhost'] = ltrim($dsnConfig['path'], '/'); + + unset($dsnConfig['scheme'], $dsnConfig['query'], $dsnConfig['fragment'], $dsnConfig['path']); + + + $config = array_replace($this->defaultConfig(), $dsnConfig); + $config = array_map(function($value) { + return urldecode($value); + }, $config); + + return $config; + } + + /** + * @return array + */ + private function defaultConfig() + { + return [ + 'host' => 'localhost', + 'port' => 5672, + 'vhost' => '/', + 'user' => 'guest', + 'pass' => 'guest', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => null, + 'persisted' => false, + 'lazy' => true, + ]; + } } diff --git a/pkg/amqp-ext/Symfony/AmqpTransportFactory.php b/pkg/amqp-ext/Symfony/AmqpTransportFactory.php index 4c1bbb2f2..66254b02d 100644 --- a/pkg/amqp-ext/Symfony/AmqpTransportFactory.php +++ b/pkg/amqp-ext/Symfony/AmqpTransportFactory.php @@ -32,7 +32,16 @@ public function __construct($name = 'amqp') public function addConfiguration(ArrayNodeDefinition $builder) { $builder + ->beforeNormalization() + ->ifString() + ->then(function ($v) { + return ['dsn' => $v]; + }) + ->end() ->children() + ->scalarNode('dsn') + ->info('The connection to AMQP broker set as a string. Other parameters are ignored if set') + ->end() ->scalarNode('host') ->defaultValue('localhost') ->cannotBeEmpty() @@ -43,12 +52,12 @@ public function addConfiguration(ArrayNodeDefinition $builder) ->cannotBeEmpty() ->info('Port on the host.') ->end() - ->scalarNode('login') + ->scalarNode('user') ->defaultValue('guest') ->cannotBeEmpty() - ->info('The login name to use. Note: Max 128 characters.') + ->info('The user name to use. Note: Max 128 characters.') ->end() - ->scalarNode('password') + ->scalarNode('pass') ->defaultValue('guest') ->cannotBeEmpty() ->info('Password. Note: Max 128 characters.') @@ -85,7 +94,7 @@ public function addConfiguration(ArrayNodeDefinition $builder) public function createConnectionFactory(ContainerBuilder $container, array $config) { $factory = new Definition(AmqpConnectionFactory::class); - $factory->setArguments([$config]); + $factory->setArguments(isset($config['dsn']) ? [$config['dsn']] : [$config]); $factoryId = sprintf('enqueue.transport.%s.connection_factory', $this->getName()); $container->setDefinition($factoryId, $factory); diff --git a/pkg/amqp-ext/Tests/AmqpConnectionFactoryConfigTest.php b/pkg/amqp-ext/Tests/AmqpConnectionFactoryConfigTest.php new file mode 100644 index 000000000..e8188ebee --- /dev/null +++ b/pkg/amqp-ext/Tests/AmqpConnectionFactoryConfigTest.php @@ -0,0 +1,167 @@ +expectException(\LogicException::class); + $this->expectExceptionMessage('The config must be eaither an array of options, a DSN string or null'); + + new AmqpConnectionFactory(new \stdClass()); + } + + public function testThrowIfSchemeIsNotAmqp() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The given DSN scheme "%s" is not supported. Could be "amqp" only.'); + + new AmqpConnectionFactory('http://example.com'); + } + + public function testThrowIfDsnCouldNotBeParsed() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Failed to parse DSN "amqp://:@/"'); + + new AmqpConnectionFactory('amqp://:@/'); + } + + /** + * @dataProvider provideConfigs + */ + public function testShouldParseConfigurationAsExpected($config, $expectedConfig) + { + $factory = new AmqpConnectionFactory($config); + + $this->assertAttributeEquals($expectedConfig, 'config', $factory); + } + + public static function provideConfigs() + { + yield [ + null, + [ + 'host' => 'localhost', + 'port' => 5672, + 'vhost' => '/', + 'user' => 'guest', + 'pass' => 'guest', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => null, + 'persisted' => false, + 'lazy' => true, + ] + ]; + + // some examples from Appendix A: Examples (https://www.rabbitmq.com/uri-spec.html) + + yield [ + "amqp://user:pass@host:10000/vhost", + [ + 'host' => 'host', + 'port' => 10000, + 'vhost' => 'vhost', + 'user' => 'user', + 'pass' => 'pass', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => null, + 'persisted' => false, + 'lazy' => true, + ] + ]; + + yield [ + "amqp://user%61:%61pass@ho%61st:10000/v%2fhost", + [ + 'host' => 'hoast', + 'port' => 10000, + 'vhost' => 'v/host', + 'user' => 'usera', + 'pass' => 'apass', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => null, + 'persisted' => false, + 'lazy' => true, + ] + ]; + + yield [ + "amqp://", + [ + 'host' => 'localhost', + 'port' => 5672, + 'vhost' => '/', + 'user' => 'guest', + 'pass' => 'guest', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => null, + 'persisted' => false, + 'lazy' => true, + ] + ]; + + yield [ + "amqp://user:pass@host:10000/vhost?connect_timeout=2&lazy=", + [ + 'host' => 'host', + 'port' => 10000, + 'vhost' => 'vhost', + 'user' => 'user', + 'pass' => 'pass', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => '2', + 'persisted' => false, + 'lazy' => '', + ] + ]; + + yield [ + [], + [ + 'host' => 'localhost', + 'port' => 5672, + 'vhost' => '/', + 'user' => 'guest', + 'pass' => 'guest', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => null, + 'persisted' => false, + 'lazy' => true, + ] + ]; + + yield [ + ['lazy' => false, 'host' => 'host'], + [ + 'host' => 'host', + 'port' => 5672, + 'vhost' => '/', + 'user' => 'guest', + 'pass' => 'guest', + 'read_timeout' => null, + 'write_timeout' => null, + 'connect_timeout' => null, + 'persisted' => false, + 'lazy' => false, + ] + ]; + } +} diff --git a/pkg/amqp-ext/Tests/AmqpConnectionFactoryTest.php b/pkg/amqp-ext/Tests/AmqpConnectionFactoryTest.php index 1826b537c..3795a04f8 100644 --- a/pkg/amqp-ext/Tests/AmqpConnectionFactoryTest.php +++ b/pkg/amqp-ext/Tests/AmqpConnectionFactoryTest.php @@ -17,42 +17,6 @@ public function testShouldImplementConnectionFactoryInterface() $this->assertClassImplements(PsrConnectionFactory::class, AmqpConnectionFactory::class); } - public function testCouldBeConstructedWithEmptyConfiguration() - { - $factory = new AmqpConnectionFactory([]); - - $this->assertAttributeEquals([ - 'host' => null, - 'port' => null, - 'vhost' => null, - 'login' => null, - 'password' => null, - 'read_timeout' => null, - 'write_timeout' => null, - 'connect_timeout' => null, - 'persisted' => false, - 'lazy' => true, - ], 'config', $factory); - } - - public function testCouldBeConstructedWithCustomConfiguration() - { - $factory = new AmqpConnectionFactory(['host' => 'theCustomHost']); - - $this->assertAttributeEquals([ - 'host' => 'theCustomHost', - 'port' => null, - 'vhost' => null, - 'login' => null, - 'password' => null, - 'read_timeout' => null, - 'write_timeout' => null, - 'connect_timeout' => null, - 'persisted' => false, - 'lazy' => true, - ], 'config', $factory); - } - public function testShouldCreateLazyContext() { $factory = new AmqpConnectionFactory(['lazy' => true]); diff --git a/pkg/amqp-ext/Tests/Symfony/AmqpTransportFactoryTest.php b/pkg/amqp-ext/Tests/Symfony/AmqpTransportFactoryTest.php index 15b83354f..a0aec30ed 100644 --- a/pkg/amqp-ext/Tests/Symfony/AmqpTransportFactoryTest.php +++ b/pkg/amqp-ext/Tests/Symfony/AmqpTransportFactoryTest.php @@ -49,8 +49,30 @@ public function testShouldAllowAddConfiguration() $this->assertEquals([ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', + 'vhost' => '/', + 'persisted' => false, + 'lazy' => true, + ], $config); + } + + public function testShouldAllowAddConfigurationAsString() + { + $transport = new AmqpTransportFactory(); + $tb = new TreeBuilder(); + $rootNode = $tb->root('foo'); + + $transport->addConfiguration($rootNode); + $processor = new Processor(); + $config = $processor->process($tb->buildTree(), ['amqpDSN']); + + $this->assertEquals([ + 'dsn' => 'amqpDSN', + 'host' => 'localhost', + 'port' => 5672, + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, 'lazy' => true, @@ -66,8 +88,8 @@ public function testShouldCreateConnectionFactory() $serviceId = $transport->createConnectionFactory($container, [ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, ]); @@ -78,13 +100,35 @@ public function testShouldCreateConnectionFactory() $this->assertSame([[ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, ]], $factory->getArguments()); } + public function testShouldCreateConnectionFactoryFromDsnString() + { + $container = new ContainerBuilder(); + + $transport = new AmqpTransportFactory(); + + $serviceId = $transport->createConnectionFactory($container, [ + 'dsn' => 'theConnectionDSN', + 'host' => 'localhost', + 'port' => 5672, + 'user' => 'guest', + 'pass' => 'guest', + 'vhost' => '/', + 'persisted' => false, + ]); + + $this->assertTrue($container->hasDefinition($serviceId)); + $factory = $container->getDefinition($serviceId); + $this->assertEquals(AmqpConnectionFactory::class, $factory->getClass()); + $this->assertSame(['theConnectionDSN'], $factory->getArguments()); + } + public function testShouldCreateContext() { $container = new ContainerBuilder(); @@ -94,8 +138,8 @@ public function testShouldCreateContext() $serviceId = $transport->createContext($container, [ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, ]); diff --git a/pkg/amqp-ext/Tests/Symfony/RabbitMqAmqpTransportFactoryTest.php b/pkg/amqp-ext/Tests/Symfony/RabbitMqAmqpTransportFactoryTest.php index fda404f67..8bf4509b4 100644 --- a/pkg/amqp-ext/Tests/Symfony/RabbitMqAmqpTransportFactoryTest.php +++ b/pkg/amqp-ext/Tests/Symfony/RabbitMqAmqpTransportFactoryTest.php @@ -55,8 +55,8 @@ public function testShouldAllowAddConfiguration() $this->assertEquals([ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, 'delay_plugin_installed' => false, @@ -73,8 +73,8 @@ public function testShouldCreateConnectionFactory() $serviceId = $transport->createConnectionFactory($container, [ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, 'delay_plugin_installed' => false, @@ -86,8 +86,8 @@ public function testShouldCreateConnectionFactory() $this->assertSame([[ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, 'delay_plugin_installed' => false, @@ -103,8 +103,8 @@ public function testShouldCreateContext() $serviceId = $transport->createContext($container, [ 'host' => 'localhost', 'port' => 5672, - 'login' => 'guest', - 'password' => 'guest', + 'user' => 'guest', + 'pass' => 'guest', 'vhost' => '/', 'persisted' => false, 'delay_plugin_installed' => false, diff --git a/pkg/amqp-ext/examples/consume.php b/pkg/amqp-ext/examples/consume.php index 6ce9a7a0e..4f74acb54 100644 --- a/pkg/amqp-ext/examples/consume.php +++ b/pkg/amqp-ext/examples/consume.php @@ -20,8 +20,8 @@ $config = [ 'host' => getenv('SYMFONY__RABBITMQ__HOST'), 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), ]; diff --git a/pkg/amqp-ext/examples/produce.php b/pkg/amqp-ext/examples/produce.php index 887575e39..8c29dcdf2 100644 --- a/pkg/amqp-ext/examples/produce.php +++ b/pkg/amqp-ext/examples/produce.php @@ -20,8 +20,8 @@ $config = [ 'host' => getenv('SYMFONY__RABBITMQ__HOST'), 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), ]; diff --git a/pkg/enqueue-bundle/Tests/Functional/RpcClientTest.php b/pkg/enqueue-bundle/Tests/Functional/RpcClientTest.php index 1a9b9b95c..91fd40e01 100644 --- a/pkg/enqueue-bundle/Tests/Functional/RpcClientTest.php +++ b/pkg/enqueue-bundle/Tests/Functional/RpcClientTest.php @@ -1,5 +1,4 @@ [ 'host' => getenv('SYMFONY__RABBITMQ__HOST'), 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), 'lazy' => false, ] diff --git a/pkg/enqueue/Tests/Functional/Client/RpcClientTest.php b/pkg/enqueue/Tests/Functional/Client/RpcClientTest.php index 49f6fa20a..55cc2eba9 100644 --- a/pkg/enqueue/Tests/Functional/Client/RpcClientTest.php +++ b/pkg/enqueue/Tests/Functional/Client/RpcClientTest.php @@ -49,8 +49,8 @@ public function testProduceAndConsumeOneMessage() 'rabbitmq_amqp' => [ 'host' => getenv('SYMFONY__RABBITMQ__HOST'), 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), ], ], diff --git a/pkg/simple-client/Tests/Functional/SimpleClientTest.php b/pkg/simple-client/Tests/Functional/SimpleClientTest.php index 7cef59d54..9bd572478 100644 --- a/pkg/simple-client/Tests/Functional/SimpleClientTest.php +++ b/pkg/simple-client/Tests/Functional/SimpleClientTest.php @@ -35,8 +35,8 @@ public function transportConfigDataProvider() 'amqp' => [ 'host' => getenv('SYMFONY__RABBITMQ__HOST'), 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), ], ], @@ -47,8 +47,8 @@ public function transportConfigDataProvider() 'rabbitmq_amqp' => [ 'host' => getenv('SYMFONY__RABBITMQ__HOST'), 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), ], ], diff --git a/pkg/test/RabbitmqAmqpExtension.php b/pkg/test/RabbitmqAmqpExtension.php index e1dba0f1a..480f99626 100644 --- a/pkg/test/RabbitmqAmqpExtension.php +++ b/pkg/test/RabbitmqAmqpExtension.php @@ -19,8 +19,8 @@ private function buildAmqpContext() $config = [ 'host' => getenv('SYMFONY__RABBITMQ__HOST'), 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), ]; From 9347ba9158958b1aa98e9d04f8cda6e56c66f966 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 12 May 2017 17:08:49 +0300 Subject: [PATCH 2/5] [symfony] dsn transport factory. --- docker-compose.yml | 2 + pkg/amqp-ext/AmqpConnectionFactory.php | 9 +- .../DependencyInjection/EnqueueExtension.php | 3 + .../Tests/Functional/UseCasesTest.php | 166 +++++++++-------- .../DependencyInjection/ConfigurationTest.php | 50 ++++-- .../EnqueueExtensionTest.php | 25 +++ pkg/enqueue/Symfony/DsnTransportFactory.php | 137 ++++++++++++++ .../Symfony/DefaultTransportFactoryTest.php | 23 +++ .../Tests/Symfony/DsnTransportFactoryTest.php | 169 ++++++++++++++++++ pkg/null/Symfony/NullTransportFactory.php | 10 ++ .../Symfony/NullTransportFactoryTest.php | 26 +++ 11 files changed, 529 insertions(+), 91 deletions(-) create mode 100644 pkg/enqueue/Symfony/DsnTransportFactory.php create mode 100644 pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php diff --git a/docker-compose.yml b/docker-compose.yml index 8a55a7ea0..9aebd7543 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,8 @@ services: volumes: - './:/mqdev' environment: + - AMQP_DSN=amqp://rabbitmq + - RABBITMQ_DSN=rabbitmq_amqp://rabbitmq - SYMFONY__RABBITMQ__HOST=rabbitmq - SYMFONY__RABBITMQ__USER=guest - SYMFONY__RABBITMQ__PASSWORD=guest diff --git a/pkg/amqp-ext/AmqpConnectionFactory.php b/pkg/amqp-ext/AmqpConnectionFactory.php index e168cf796..05b4f6e39 100644 --- a/pkg/amqp-ext/AmqpConnectionFactory.php +++ b/pkg/amqp-ext/AmqpConnectionFactory.php @@ -68,10 +68,17 @@ public function createContext() return new AmqpContext(new \AMQPChannel($this->establishConnection())); } + /** + * @return \AMQPConnection + */ private function establishConnection() { if (false == $this->connection) { - $this->connection = new \AMQPConnection($this->config); + $config = $this->config; + $config['login'] = $this->config['user']; + $config['password'] = $this->config['pass']; + + $this->connection = new \AMQPConnection($config); $this->config['persisted'] ? $this->connection->pconnect() : $this->connection->connect(); } diff --git a/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php b/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php index 0ba9dcf2e..612987a33 100644 --- a/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php +++ b/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php @@ -4,6 +4,7 @@ use Enqueue\Client\TraceableProducer; use Enqueue\JobQueue\Job; +use Enqueue\Symfony\DsnTransportFactory; use Enqueue\Symfony\TransportFactoryInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\FileResource; @@ -47,6 +48,8 @@ public function addTransportFactory(TransportFactoryInterface $transportFactory) */ public function load(array $configs, ContainerBuilder $container) { + $this->factories['dsn'] = new DsnTransportFactory($this->factories); + $config = $this->processConfiguration(new Configuration($this->factories), $configs); $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); diff --git a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php index 502752e53..1a23db552 100644 --- a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php +++ b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php @@ -16,87 +16,105 @@ class UseCasesTest extends WebTestCase { public function provideEnqueueConfigs() { - return [ - ['amqp' => [ - 'transport' => [ - 'default' => 'amqp', - 'amqp' => [ - 'host' => getenv('SYMFONY__RABBITMQ__HOST'), - 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'user' => getenv('SYMFONY__RABBITMQ__USER'), - 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), - 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), - 'lazy' => false, - ] + yield 'amqp' => [[ + 'transport' => [ + 'default' => 'amqp', + 'amqp' => [ + 'host' => getenv('SYMFONY__RABBITMQ__HOST'), + 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), + 'lazy' => false, ] - ]], - ['stomp' => [ - 'transport' => [ - 'default' => 'stomp', - 'stomp' => [ - 'host' => getenv('SYMFONY__RABBITMQ__HOST'), - 'port' => getenv('SYMFONY__RABBITMQ__STOMP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), - 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), - 'lazy' => false, - ] + ] + ]]; + + yield 'amqp_dsn' => [[ + 'transport' => [ + 'default' => 'amqp', + 'amqp' => getenv('AMQP_DSN'), + ] + ]]; + + yield 'dsn_amqp' => [[ + 'transport' => [ + 'default' => 'dsn', + 'dsn' => getenv('AMQP_DSN'), + ] + ]]; + + yield 'stomp' => [[ + 'transport' => [ + 'default' => 'stomp', + 'stomp' => [ + 'host' => getenv('SYMFONY__RABBITMQ__HOST'), + 'port' => getenv('SYMFONY__RABBITMQ__STOMP__PORT'), + 'login' => getenv('SYMFONY__RABBITMQ__USER'), + 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), + 'lazy' => false, ] - ]], - ['predis' => [ - 'transport' => [ - 'default' => 'redis', - 'redis' => [ - 'host' => getenv('SYMFONY__REDIS__HOST'), - 'port' => (int) getenv('SYMFONY__REDIS__PORT'), - 'vendor' => 'predis', - 'lazy' => false, - ] + ] + ]]; + + yield 'predis' => [[ + 'transport' => [ + 'default' => 'redis', + 'redis' => [ + 'host' => getenv('SYMFONY__REDIS__HOST'), + 'port' => (int) getenv('SYMFONY__REDIS__PORT'), + 'vendor' => 'predis', + 'lazy' => false, ] - ]], - ['phpredis' => [ - 'transport' => [ - 'default' => 'redis', - 'redis' => [ - 'host' => getenv('SYMFONY__REDIS__HOST'), - 'port' => (int) getenv('SYMFONY__REDIS__PORT'), - 'vendor' => 'phpredis', - 'lazy' => false, - ] + ] + ]]; + + yield 'phpredis' => [[ + 'transport' => [ + 'default' => 'redis', + 'redis' => [ + 'host' => getenv('SYMFONY__REDIS__HOST'), + 'port' => (int) getenv('SYMFONY__REDIS__PORT'), + 'vendor' => 'phpredis', + 'lazy' => false, ] - ]], - ['fs' => [ - 'transport' => [ - 'default' => 'fs', - 'fs' => [ - 'store_dir' => sys_get_temp_dir(), - ] + ] + ]]; + + yield 'fs' => [[ + 'transport' => [ + 'default' => 'fs', + 'fs' => [ + 'store_dir' => sys_get_temp_dir(), ] - ]], - ['dbal' => [ - 'transport' => [ - 'default' => 'dbal', - 'dbal' => [ - 'dbname' => getenv('SYMFONY__DB__NAME'), - 'user' => getenv('SYMFONY__DB__USER'), - 'password' => getenv('SYMFONY__DB__PASSWORD'), - 'host' => getenv('SYMFONY__DB__HOST'), - 'port' => getenv('SYMFONY__DB__PORT'), - 'driver' => getenv('SYMFONY__DB__DRIVER'), - ] + ] + ]]; + + yield 'dbal' => [[ + 'transport' => [ + 'default' => 'dbal', + 'dbal' => [ + 'dbname' => getenv('SYMFONY__DB__NAME'), + 'user' => getenv('SYMFONY__DB__USER'), + 'password' => getenv('SYMFONY__DB__PASSWORD'), + 'host' => getenv('SYMFONY__DB__HOST'), + 'port' => getenv('SYMFONY__DB__PORT'), + 'driver' => getenv('SYMFONY__DB__DRIVER'), ] - ]], - ['sqs' => [ - 'transport' => [ - 'default' => 'sqs', - 'sqs' => [ - 'key' => getenv('AWS__SQS__KEY'), - 'secret' => getenv('AWS__SQS__SECRET'), - 'region' => getenv('AWS__SQS__REGION'), - ] + ] + ]]; + + yield 'sqs' => [[ + 'transport' => [ + 'default' => 'sqs', + 'sqs' => [ + 'key' => getenv('AWS__SQS__KEY'), + 'secret' => getenv('AWS__SQS__SECRET'), + 'region' => getenv('AWS__SQS__REGION'), ] - ]], - ]; + ] + ]]; } /** diff --git a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php index 0ae61b208..cf1f0c375 100644 --- a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php @@ -6,6 +6,7 @@ use Enqueue\Bundle\Tests\Unit\Mocks\FooTransportFactory; use Enqueue\Symfony\DefaultTransportFactory; use Enqueue\Null\Symfony\NullTransportFactory; +use Enqueue\Symfony\DsnTransportFactory; use Enqueue\Test\ClassExtensionTrait; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; @@ -28,10 +29,8 @@ public function testCouldBeConstructedWithFactoriesAsFirstArgument() public function testThrowIfTransportNotConfigured() { - $this->setExpectedException( - InvalidConfigurationException::class, - 'The child node "transport" at path "enqueue" must be configured.' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The child node "transport" at path "enqueue" must be configured.'); $configuration = new Configuration([]); @@ -59,10 +58,8 @@ public function testThrowExceptionIfFooTransportConfigInvalid() $processor = new Processor(); - $this->setExpectedException( - InvalidConfigurationException::class, - 'The path "enqueue.transport.foo.foo_param" cannot contain an empty value, but got null.' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The path "enqueue.transport.foo.foo_param" cannot contain an empty value, but got null.'); $processor->processConfiguration($configuration, [[ 'transport' => [ @@ -103,6 +100,31 @@ public function testShouldAllowConfigureNullTransport() ], $config); } + public function testShouldAllowConfigureNullTransportViaDsnTransport() + { + $nullFactory = new NullTransportFactory(); + + $configuration = new Configuration([ + $nullFactory, + new DsnTransportFactory([$nullFactory]) + ]); + + $processor = new Processor(); + $config = $processor->processConfiguration($configuration, [[ + 'transport' => [ + 'dsn' => 'null://', + ], + ]]); + + $this->assertArraySubset([ + 'transport' => [ + 'dsn' => [ + 'dsn' => 'null://' + ], + ], + ], $config); + } + public function testShouldAllowConfigureSeveralTransportsSameTime() { $configuration = new Configuration([ @@ -160,10 +182,8 @@ public function testShouldSetDefaultConfigurationForClient() public function testThrowExceptionIfRouterTopicIsEmpty() { - $this->setExpectedException( - InvalidConfigurationException::class, - 'The path "enqueue.client.router_topic" cannot contain an empty value, but got "".' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The path "enqueue.client.router_topic" cannot contain an empty value, but got "".'); $configuration = new Configuration([new DefaultTransportFactory()]); @@ -180,10 +200,8 @@ public function testThrowExceptionIfRouterTopicIsEmpty() public function testThrowExceptionIfRouterQueueIsEmpty() { - $this->setExpectedException( - InvalidConfigurationException::class, - 'The path "enqueue.client.router_queue" cannot contain an empty value, but got "".' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The path "enqueue.client.router_queue" cannot contain an empty value, but got "".'); $configuration = new Configuration([new DefaultTransportFactory()]); diff --git a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php index 84210f390..49a5733a6 100644 --- a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php @@ -95,6 +95,31 @@ public function testShouldUseNullTransportAsDefault() ); } + public function testShouldUseNullTransportAsDefaultConfiguredViaDSN() + { + $container = new ContainerBuilder(); + + $extension = new EnqueueExtension(); + $extension->addTransportFactory(new NullTransportFactory()); + $extension->addTransportFactory(new DefaultTransportFactory()); + + $extension->load([[ + 'transport' => [ + 'default' => 'dsn', + 'dsn' => 'null://', + ], + ]], $container); + + self::assertEquals( + 'enqueue.transport.default.context', + (string) $container->getAlias('enqueue.transport.context') + ); + self::assertEquals( + 'enqueue.transport.dsn.context', + (string) $container->getAlias('enqueue.transport.default.context') + ); + } + public function testShouldConfigureFooTransport() { $container = new ContainerBuilder(); diff --git a/pkg/enqueue/Symfony/DsnTransportFactory.php b/pkg/enqueue/Symfony/DsnTransportFactory.php new file mode 100644 index 000000000..26b4b6aa6 --- /dev/null +++ b/pkg/enqueue/Symfony/DsnTransportFactory.php @@ -0,0 +1,137 @@ +name = $name; + + $this->factories = []; + foreach ($factories as $factory) { + $this->factories[$factory->getName()] = $factory; + } + } + + /** + * {@inheritdoc} + */ + public function addConfiguration(ArrayNodeDefinition $builder) + { + $builder + ->beforeNormalization() + ->ifString() + ->then(function ($v) { + return ['dsn' => $v]; + }) + ->end() + ->children() + ->scalarNode('dsn')->isRequired()->cannotBeEmpty()->end() + ; + } + + public function createConnectionFactory(ContainerBuilder $container, array $config) + { + $factoryId = $this->findFactory($config['dsn'])->createConnectionFactory($container, [ + 'dsn' => $config['dsn'] + ]); + + $container->setAlias( + sprintf('enqueue.transport.%s.connection_factory', $this->getName()), + $factoryId + ); + + return $factoryId; + } + + /** + * {@inheritdoc} + */ + public function createContext(ContainerBuilder $container, array $config) + { + $contextId = $this->findFactory($config['dsn'])->createContext($container, [ + 'dsn' => $config['dsn'] + ]); + + $container->setAlias( + sprintf('enqueue.transport.%s.context', $this->getName()), + $contextId + ); + + return $contextId; + } + + /** + * {@inheritdoc} + */ + public function createDriver(ContainerBuilder $container, array $config) + { + $driverId = $this->findFactory($config['dsn'])->createDriver($container, [ + 'dsn' => $config['dsn'] + ]); + + $container->setAlias( + sprintf('enqueue.transport.%s.driver', $this->getName()), + $driverId + ); + + return $driverId; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string + * + * @return TransportFactoryInterface + */ + private function findFactory($dsn) + { + list($scheme) = explode('://', $dsn); + + if (false == $scheme || false === strpos($dsn, '://')) { + throw new \LogicException(sprintf('The scheme could not be parsed from DSN "%s"', $dsn)); + } + + $supportedSchemes = ['amqp', 'rabbitmq_amqp', 'null']; + if (false == in_array($scheme, $supportedSchemes)) { + throw new \LogicException(sprintf('The scheme "%s" is not supported.', $scheme)); + } + + if (false == array_key_exists($scheme, $this->factories)) { + throw new \LogicException(sprintf( + 'There is no factory that supports requested schema "%s", available are "%s"', + $scheme, + implode('", "', array_keys($this->factories)) + )); + } + + return $this->factories[$scheme]; + } +} diff --git a/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php b/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php index 39cdca9c2..865ef6793 100644 --- a/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php +++ b/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php @@ -46,6 +46,29 @@ public function testShouldAllowAddConfiguration() $this->assertEquals(['alias' => 'the_alias'], $config); } + public function testShouldCreateConnectionFactory() + { + $container = new ContainerBuilder(); + + $transport = new DefaultTransportFactory(); + + $serviceId = $transport->createConnectionFactory($container, ['alias' => 'foo']); + + $this->assertEquals('enqueue.transport.default.connection_factory', $serviceId); + + $this->assertTrue($container->hasAlias('enqueue.transport.default.connection_factory')); + $this->assertEquals( + 'enqueue.transport.foo.connection_factory', + (string) $container->getAlias('enqueue.transport.default.connection_factory') + ); + + $this->assertTrue($container->hasAlias('enqueue.transport.connection_factory')); + $this->assertEquals( + 'enqueue.transport.default.connection_factory', + (string) $container->getAlias('enqueue.transport.connection_factory') + ); + } + public function testShouldCreateContext() { $container = new ContainerBuilder(); diff --git a/pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php b/pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php new file mode 100644 index 000000000..e2009f76e --- /dev/null +++ b/pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php @@ -0,0 +1,169 @@ +assertClassImplements(TransportFactoryInterface::class, DsnTransportFactory::class); + } + + public function testCouldBeConstructedWithDefaultName() + { + $transport = new DsnTransportFactory([]); + + $this->assertEquals('dsn', $transport->getName()); + } + + public function testCouldBeConstructedWithCustomName() + { + $transport = new DsnTransportFactory([], 'theCustomName'); + + $this->assertEquals('theCustomName', $transport->getName()); + } + + public function testShouldAllowAddConfigurationAsString() + { + $transport = new DsnTransportFactory([]); + $tb = new TreeBuilder(); + $rootNode = $tb->root('foo'); + + $transport->addConfiguration($rootNode); + $processor = new Processor(); + $config = $processor->process($tb->buildTree(), ['amqp://example.com']); + + $this->assertEquals(['dsn' => 'amqp://example.com'], $config); + } + + public function testShouldAllowAddConfigurationAsOption() + { + $transport = new DsnTransportFactory([]); + $tb = new TreeBuilder(); + $rootNode = $tb->root('foo'); + + $transport->addConfiguration($rootNode); + $processor = new Processor(); + $config = $processor->process($tb->buildTree(), [['dsn' => 'amqp://example.com']]); + + $this->assertEquals(['dsn' => 'amqp://example.com'], $config); + } + + public function testThrowIfSchemeNotParsedOnCreateConnectionFactory() + { + $transport = new DsnTransportFactory([]); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The scheme could not be parsed from DSN "invalidDsn"'); + + $transport->createConnectionFactory(new ContainerBuilder(), ['dsn' => 'invalidDsn']); + } + + public function testThrowIfSchemeNotSupportedOnCreateConnectionFactory() + { + $transport = new DsnTransportFactory([]); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The scheme "http" is not supported.'); + + $transport->createConnectionFactory(new ContainerBuilder(), ['dsn' => 'http://foo.bar']); + } + + public function testThrowIfThereIsFactoryRegistered() + { + $transport = new DsnTransportFactory([ + $this->createTransportFactoryStub('foo'), + $this->createTransportFactoryStub('bar'), + ]); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('There is no factory that supports requested schema "amqp", available are "foo", "bar"'); + + $transport->createConnectionFactory(new ContainerBuilder(), ['dsn' => 'amqp://foo']); + } + + public function testShouldProxyCallToInternalFactoryCreateConnectionFactoryMethod() + { + $container = new ContainerBuilder(); + + $internalFactory = $this->createTransportFactoryStub('amqp'); + $internalFactory + ->expects($this->once()) + ->method('createConnectionFactory') + ->with($this->identicalTo($container), ['dsn' => 'amqp://example.com']) + ->willReturn('theServiceId') + ; + + $transport = new DsnTransportFactory([$internalFactory]); + + $serviceId = $transport->createConnectionFactory($container, ['dsn' => 'amqp://example.com']); + + $this->assertEquals('theServiceId', $serviceId); + } + + public function testShouldProxyCallToInternalCreateContextMethod() + { + $container = new ContainerBuilder(); + + $internalFactory = $this->createTransportFactoryStub('amqp'); + $internalFactory + ->expects($this->once()) + ->method('createContext') + ->with($this->identicalTo($container), ['dsn' => 'amqp://example.com']) + ->willReturn('theServiceId') + ; + + $transport = new DsnTransportFactory([$internalFactory]); + + $serviceId = $transport->createContext($container, ['dsn' => 'amqp://example.com']); + + $this->assertEquals('theServiceId', $serviceId); + } + + public function testShouldProxyCallToInternalCreateDriverMethod() + { + $container = new ContainerBuilder(); + + $internalFactory = $this->createTransportFactoryStub('amqp'); + $internalFactory + ->expects($this->once()) + ->method('createDriver') + ->with($this->identicalTo($container), ['dsn' => 'amqp://example.com']) + ->willReturn('theServiceId') + ; + + $transport = new DsnTransportFactory([$internalFactory]); + + $serviceId = $transport->createDriver($container, ['dsn' => 'amqp://example.com']); + + $this->assertEquals('theServiceId', $serviceId); + } + + /** + * @param mixed $name + * + * @return \PHPUnit_Framework_MockObject_MockObject|TransportFactoryInterface + */ + private function createTransportFactoryStub($name) + { + $factoryMock = $this->createMock(TransportFactoryInterface::class); + $factoryMock + ->expects($this->any()) + ->method('getName') + ->willReturn($name) + ; + + return $factoryMock; + } +} diff --git a/pkg/null/Symfony/NullTransportFactory.php b/pkg/null/Symfony/NullTransportFactory.php index b18d38474..863489b0e 100644 --- a/pkg/null/Symfony/NullTransportFactory.php +++ b/pkg/null/Symfony/NullTransportFactory.php @@ -31,6 +31,16 @@ public function __construct($name = 'null') */ public function addConfiguration(ArrayNodeDefinition $builder) { + $builder + ->beforeNormalization() + ->ifString()->then(function ($v) { + return ['dsn' => $v]; + }) + ->end() + ->children() + ->scalarNode('dsn')->end() + ->end() + ; } /** diff --git a/pkg/null/Tests/Symfony/NullTransportFactoryTest.php b/pkg/null/Tests/Symfony/NullTransportFactoryTest.php index 07ee32973..96c2ddf0d 100644 --- a/pkg/null/Tests/Symfony/NullTransportFactoryTest.php +++ b/pkg/null/Tests/Symfony/NullTransportFactoryTest.php @@ -50,6 +50,32 @@ public function testShouldAllowAddConfiguration() $this->assertEquals([], $config); } + public function testShouldAllowAddConfigurationWithDsnString() + { + $transport = new NullTransportFactory(); + $tb = new TreeBuilder(); + $rootNode = $tb->root('foo'); + + $transport->addConfiguration($rootNode); + $processor = new Processor(); + $config = $processor->process($tb->buildTree(), ['aStringDSN']); + + $this->assertEquals(['dsn' => 'aStringDSN'], $config); + } + + public function testShouldAllowAddConfigurationWithDsnStringOption() + { + $transport = new NullTransportFactory(); + $tb = new TreeBuilder(); + $rootNode = $tb->root('foo'); + + $transport->addConfiguration($rootNode); + $processor = new Processor(); + $config = $processor->process($tb->buildTree(), [['dsn' => 'aStringDSN']]); + + $this->assertEquals(['dsn' => 'aStringDSN'], $config); + } + public function testShouldCreateConnectionFactory() { $container = new ContainerBuilder(); From 161065bbd513cb996cefd15a398488575f9d079a Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 12 May 2017 17:10:23 +0300 Subject: [PATCH 3/5] fix doc. --- docs/transport/amqp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/transport/amqp.md b/docs/transport/amqp.md index ebab8a093..0862cee10 100644 --- a/docs/transport/amqp.md +++ b/docs/transport/amqp.md @@ -45,7 +45,7 @@ $connectionFactory = new AmqpConnectionFactory([ ]); // same as above but given as DSN string -$connectionFactory = new AmqpConnectionFactory('amqp://user:pass:10000@example.com/%2f'); +$connectionFactory = new AmqpConnectionFactory('amqp://user:pass@example.com:10000/%2f'); $psrContext = $connectionFactory->createContext(); ``` From e4306f5ee691c9911342a6434aa0c6aebe274469 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 12 May 2017 22:31:32 +0300 Subject: [PATCH 4/5] Revert "[symfony] dsn transport factory." This reverts commit 9347ba9158958b1aa98e9d04f8cda6e56c66f966. --- docker-compose.yml | 2 - pkg/amqp-ext/AmqpConnectionFactory.php | 9 +- .../DependencyInjection/EnqueueExtension.php | 3 - .../Tests/Functional/UseCasesTest.php | 166 ++++++++--------- .../DependencyInjection/ConfigurationTest.php | 50 ++---- .../EnqueueExtensionTest.php | 25 --- pkg/enqueue/Symfony/DsnTransportFactory.php | 137 -------------- .../Symfony/DefaultTransportFactoryTest.php | 23 --- .../Tests/Symfony/DsnTransportFactoryTest.php | 169 ------------------ pkg/null/Symfony/NullTransportFactory.php | 10 -- .../Symfony/NullTransportFactoryTest.php | 26 --- 11 files changed, 91 insertions(+), 529 deletions(-) delete mode 100644 pkg/enqueue/Symfony/DsnTransportFactory.php delete mode 100644 pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php diff --git a/docker-compose.yml b/docker-compose.yml index 9aebd7543..8a55a7ea0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,8 +10,6 @@ services: volumes: - './:/mqdev' environment: - - AMQP_DSN=amqp://rabbitmq - - RABBITMQ_DSN=rabbitmq_amqp://rabbitmq - SYMFONY__RABBITMQ__HOST=rabbitmq - SYMFONY__RABBITMQ__USER=guest - SYMFONY__RABBITMQ__PASSWORD=guest diff --git a/pkg/amqp-ext/AmqpConnectionFactory.php b/pkg/amqp-ext/AmqpConnectionFactory.php index 05b4f6e39..e168cf796 100644 --- a/pkg/amqp-ext/AmqpConnectionFactory.php +++ b/pkg/amqp-ext/AmqpConnectionFactory.php @@ -68,17 +68,10 @@ public function createContext() return new AmqpContext(new \AMQPChannel($this->establishConnection())); } - /** - * @return \AMQPConnection - */ private function establishConnection() { if (false == $this->connection) { - $config = $this->config; - $config['login'] = $this->config['user']; - $config['password'] = $this->config['pass']; - - $this->connection = new \AMQPConnection($config); + $this->connection = new \AMQPConnection($this->config); $this->config['persisted'] ? $this->connection->pconnect() : $this->connection->connect(); } diff --git a/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php b/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php index 612987a33..0ba9dcf2e 100644 --- a/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php +++ b/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php @@ -4,7 +4,6 @@ use Enqueue\Client\TraceableProducer; use Enqueue\JobQueue\Job; -use Enqueue\Symfony\DsnTransportFactory; use Enqueue\Symfony\TransportFactoryInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\FileResource; @@ -48,8 +47,6 @@ public function addTransportFactory(TransportFactoryInterface $transportFactory) */ public function load(array $configs, ContainerBuilder $container) { - $this->factories['dsn'] = new DsnTransportFactory($this->factories); - $config = $this->processConfiguration(new Configuration($this->factories), $configs); $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); diff --git a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php index 1a23db552..502752e53 100644 --- a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php +++ b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php @@ -16,105 +16,87 @@ class UseCasesTest extends WebTestCase { public function provideEnqueueConfigs() { - yield 'amqp' => [[ - 'transport' => [ - 'default' => 'amqp', - 'amqp' => [ - 'host' => getenv('SYMFONY__RABBITMQ__HOST'), - 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'user' => getenv('SYMFONY__RABBITMQ__USER'), - 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), - 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), - 'lazy' => false, + return [ + ['amqp' => [ + 'transport' => [ + 'default' => 'amqp', + 'amqp' => [ + 'host' => getenv('SYMFONY__RABBITMQ__HOST'), + 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), + 'lazy' => false, + ] ] - ] - ]]; - - yield 'amqp_dsn' => [[ - 'transport' => [ - 'default' => 'amqp', - 'amqp' => getenv('AMQP_DSN'), - ] - ]]; - - yield 'dsn_amqp' => [[ - 'transport' => [ - 'default' => 'dsn', - 'dsn' => getenv('AMQP_DSN'), - ] - ]]; - - yield 'stomp' => [[ - 'transport' => [ - 'default' => 'stomp', - 'stomp' => [ - 'host' => getenv('SYMFONY__RABBITMQ__HOST'), - 'port' => getenv('SYMFONY__RABBITMQ__STOMP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), - 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), - 'lazy' => false, + ]], + ['stomp' => [ + 'transport' => [ + 'default' => 'stomp', + 'stomp' => [ + 'host' => getenv('SYMFONY__RABBITMQ__HOST'), + 'port' => getenv('SYMFONY__RABBITMQ__STOMP__PORT'), + 'login' => getenv('SYMFONY__RABBITMQ__USER'), + 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), + 'lazy' => false, + ] ] - ] - ]]; - - yield 'predis' => [[ - 'transport' => [ - 'default' => 'redis', - 'redis' => [ - 'host' => getenv('SYMFONY__REDIS__HOST'), - 'port' => (int) getenv('SYMFONY__REDIS__PORT'), - 'vendor' => 'predis', - 'lazy' => false, + ]], + ['predis' => [ + 'transport' => [ + 'default' => 'redis', + 'redis' => [ + 'host' => getenv('SYMFONY__REDIS__HOST'), + 'port' => (int) getenv('SYMFONY__REDIS__PORT'), + 'vendor' => 'predis', + 'lazy' => false, + ] ] - ] - ]]; - - yield 'phpredis' => [[ - 'transport' => [ - 'default' => 'redis', - 'redis' => [ - 'host' => getenv('SYMFONY__REDIS__HOST'), - 'port' => (int) getenv('SYMFONY__REDIS__PORT'), - 'vendor' => 'phpredis', - 'lazy' => false, + ]], + ['phpredis' => [ + 'transport' => [ + 'default' => 'redis', + 'redis' => [ + 'host' => getenv('SYMFONY__REDIS__HOST'), + 'port' => (int) getenv('SYMFONY__REDIS__PORT'), + 'vendor' => 'phpredis', + 'lazy' => false, + ] ] - ] - ]]; - - yield 'fs' => [[ - 'transport' => [ - 'default' => 'fs', - 'fs' => [ - 'store_dir' => sys_get_temp_dir(), + ]], + ['fs' => [ + 'transport' => [ + 'default' => 'fs', + 'fs' => [ + 'store_dir' => sys_get_temp_dir(), + ] ] - ] - ]]; - - yield 'dbal' => [[ - 'transport' => [ - 'default' => 'dbal', - 'dbal' => [ - 'dbname' => getenv('SYMFONY__DB__NAME'), - 'user' => getenv('SYMFONY__DB__USER'), - 'password' => getenv('SYMFONY__DB__PASSWORD'), - 'host' => getenv('SYMFONY__DB__HOST'), - 'port' => getenv('SYMFONY__DB__PORT'), - 'driver' => getenv('SYMFONY__DB__DRIVER'), + ]], + ['dbal' => [ + 'transport' => [ + 'default' => 'dbal', + 'dbal' => [ + 'dbname' => getenv('SYMFONY__DB__NAME'), + 'user' => getenv('SYMFONY__DB__USER'), + 'password' => getenv('SYMFONY__DB__PASSWORD'), + 'host' => getenv('SYMFONY__DB__HOST'), + 'port' => getenv('SYMFONY__DB__PORT'), + 'driver' => getenv('SYMFONY__DB__DRIVER'), + ] ] - ] - ]]; - - yield 'sqs' => [[ - 'transport' => [ - 'default' => 'sqs', - 'sqs' => [ - 'key' => getenv('AWS__SQS__KEY'), - 'secret' => getenv('AWS__SQS__SECRET'), - 'region' => getenv('AWS__SQS__REGION'), + ]], + ['sqs' => [ + 'transport' => [ + 'default' => 'sqs', + 'sqs' => [ + 'key' => getenv('AWS__SQS__KEY'), + 'secret' => getenv('AWS__SQS__SECRET'), + 'region' => getenv('AWS__SQS__REGION'), + ] ] - ] - ]]; + ]], + ]; } /** diff --git a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php index cf1f0c375..0ae61b208 100644 --- a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php @@ -6,7 +6,6 @@ use Enqueue\Bundle\Tests\Unit\Mocks\FooTransportFactory; use Enqueue\Symfony\DefaultTransportFactory; use Enqueue\Null\Symfony\NullTransportFactory; -use Enqueue\Symfony\DsnTransportFactory; use Enqueue\Test\ClassExtensionTrait; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; @@ -29,8 +28,10 @@ public function testCouldBeConstructedWithFactoriesAsFirstArgument() public function testThrowIfTransportNotConfigured() { - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('The child node "transport" at path "enqueue" must be configured.'); + $this->setExpectedException( + InvalidConfigurationException::class, + 'The child node "transport" at path "enqueue" must be configured.' + ); $configuration = new Configuration([]); @@ -58,8 +59,10 @@ public function testThrowExceptionIfFooTransportConfigInvalid() $processor = new Processor(); - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('The path "enqueue.transport.foo.foo_param" cannot contain an empty value, but got null.'); + $this->setExpectedException( + InvalidConfigurationException::class, + 'The path "enqueue.transport.foo.foo_param" cannot contain an empty value, but got null.' + ); $processor->processConfiguration($configuration, [[ 'transport' => [ @@ -100,31 +103,6 @@ public function testShouldAllowConfigureNullTransport() ], $config); } - public function testShouldAllowConfigureNullTransportViaDsnTransport() - { - $nullFactory = new NullTransportFactory(); - - $configuration = new Configuration([ - $nullFactory, - new DsnTransportFactory([$nullFactory]) - ]); - - $processor = new Processor(); - $config = $processor->processConfiguration($configuration, [[ - 'transport' => [ - 'dsn' => 'null://', - ], - ]]); - - $this->assertArraySubset([ - 'transport' => [ - 'dsn' => [ - 'dsn' => 'null://' - ], - ], - ], $config); - } - public function testShouldAllowConfigureSeveralTransportsSameTime() { $configuration = new Configuration([ @@ -182,8 +160,10 @@ public function testShouldSetDefaultConfigurationForClient() public function testThrowExceptionIfRouterTopicIsEmpty() { - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('The path "enqueue.client.router_topic" cannot contain an empty value, but got "".'); + $this->setExpectedException( + InvalidConfigurationException::class, + 'The path "enqueue.client.router_topic" cannot contain an empty value, but got "".' + ); $configuration = new Configuration([new DefaultTransportFactory()]); @@ -200,8 +180,10 @@ public function testThrowExceptionIfRouterTopicIsEmpty() public function testThrowExceptionIfRouterQueueIsEmpty() { - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('The path "enqueue.client.router_queue" cannot contain an empty value, but got "".'); + $this->setExpectedException( + InvalidConfigurationException::class, + 'The path "enqueue.client.router_queue" cannot contain an empty value, but got "".' + ); $configuration = new Configuration([new DefaultTransportFactory()]); diff --git a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php index 49a5733a6..84210f390 100644 --- a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php @@ -95,31 +95,6 @@ public function testShouldUseNullTransportAsDefault() ); } - public function testShouldUseNullTransportAsDefaultConfiguredViaDSN() - { - $container = new ContainerBuilder(); - - $extension = new EnqueueExtension(); - $extension->addTransportFactory(new NullTransportFactory()); - $extension->addTransportFactory(new DefaultTransportFactory()); - - $extension->load([[ - 'transport' => [ - 'default' => 'dsn', - 'dsn' => 'null://', - ], - ]], $container); - - self::assertEquals( - 'enqueue.transport.default.context', - (string) $container->getAlias('enqueue.transport.context') - ); - self::assertEquals( - 'enqueue.transport.dsn.context', - (string) $container->getAlias('enqueue.transport.default.context') - ); - } - public function testShouldConfigureFooTransport() { $container = new ContainerBuilder(); diff --git a/pkg/enqueue/Symfony/DsnTransportFactory.php b/pkg/enqueue/Symfony/DsnTransportFactory.php deleted file mode 100644 index 26b4b6aa6..000000000 --- a/pkg/enqueue/Symfony/DsnTransportFactory.php +++ /dev/null @@ -1,137 +0,0 @@ -name = $name; - - $this->factories = []; - foreach ($factories as $factory) { - $this->factories[$factory->getName()] = $factory; - } - } - - /** - * {@inheritdoc} - */ - public function addConfiguration(ArrayNodeDefinition $builder) - { - $builder - ->beforeNormalization() - ->ifString() - ->then(function ($v) { - return ['dsn' => $v]; - }) - ->end() - ->children() - ->scalarNode('dsn')->isRequired()->cannotBeEmpty()->end() - ; - } - - public function createConnectionFactory(ContainerBuilder $container, array $config) - { - $factoryId = $this->findFactory($config['dsn'])->createConnectionFactory($container, [ - 'dsn' => $config['dsn'] - ]); - - $container->setAlias( - sprintf('enqueue.transport.%s.connection_factory', $this->getName()), - $factoryId - ); - - return $factoryId; - } - - /** - * {@inheritdoc} - */ - public function createContext(ContainerBuilder $container, array $config) - { - $contextId = $this->findFactory($config['dsn'])->createContext($container, [ - 'dsn' => $config['dsn'] - ]); - - $container->setAlias( - sprintf('enqueue.transport.%s.context', $this->getName()), - $contextId - ); - - return $contextId; - } - - /** - * {@inheritdoc} - */ - public function createDriver(ContainerBuilder $container, array $config) - { - $driverId = $this->findFactory($config['dsn'])->createDriver($container, [ - 'dsn' => $config['dsn'] - ]); - - $container->setAlias( - sprintf('enqueue.transport.%s.driver', $this->getName()), - $driverId - ); - - return $driverId; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @param string - * - * @return TransportFactoryInterface - */ - private function findFactory($dsn) - { - list($scheme) = explode('://', $dsn); - - if (false == $scheme || false === strpos($dsn, '://')) { - throw new \LogicException(sprintf('The scheme could not be parsed from DSN "%s"', $dsn)); - } - - $supportedSchemes = ['amqp', 'rabbitmq_amqp', 'null']; - if (false == in_array($scheme, $supportedSchemes)) { - throw new \LogicException(sprintf('The scheme "%s" is not supported.', $scheme)); - } - - if (false == array_key_exists($scheme, $this->factories)) { - throw new \LogicException(sprintf( - 'There is no factory that supports requested schema "%s", available are "%s"', - $scheme, - implode('", "', array_keys($this->factories)) - )); - } - - return $this->factories[$scheme]; - } -} diff --git a/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php b/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php index 865ef6793..39cdca9c2 100644 --- a/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php +++ b/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php @@ -46,29 +46,6 @@ public function testShouldAllowAddConfiguration() $this->assertEquals(['alias' => 'the_alias'], $config); } - public function testShouldCreateConnectionFactory() - { - $container = new ContainerBuilder(); - - $transport = new DefaultTransportFactory(); - - $serviceId = $transport->createConnectionFactory($container, ['alias' => 'foo']); - - $this->assertEquals('enqueue.transport.default.connection_factory', $serviceId); - - $this->assertTrue($container->hasAlias('enqueue.transport.default.connection_factory')); - $this->assertEquals( - 'enqueue.transport.foo.connection_factory', - (string) $container->getAlias('enqueue.transport.default.connection_factory') - ); - - $this->assertTrue($container->hasAlias('enqueue.transport.connection_factory')); - $this->assertEquals( - 'enqueue.transport.default.connection_factory', - (string) $container->getAlias('enqueue.transport.connection_factory') - ); - } - public function testShouldCreateContext() { $container = new ContainerBuilder(); diff --git a/pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php b/pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php deleted file mode 100644 index e2009f76e..000000000 --- a/pkg/enqueue/Tests/Symfony/DsnTransportFactoryTest.php +++ /dev/null @@ -1,169 +0,0 @@ -assertClassImplements(TransportFactoryInterface::class, DsnTransportFactory::class); - } - - public function testCouldBeConstructedWithDefaultName() - { - $transport = new DsnTransportFactory([]); - - $this->assertEquals('dsn', $transport->getName()); - } - - public function testCouldBeConstructedWithCustomName() - { - $transport = new DsnTransportFactory([], 'theCustomName'); - - $this->assertEquals('theCustomName', $transport->getName()); - } - - public function testShouldAllowAddConfigurationAsString() - { - $transport = new DsnTransportFactory([]); - $tb = new TreeBuilder(); - $rootNode = $tb->root('foo'); - - $transport->addConfiguration($rootNode); - $processor = new Processor(); - $config = $processor->process($tb->buildTree(), ['amqp://example.com']); - - $this->assertEquals(['dsn' => 'amqp://example.com'], $config); - } - - public function testShouldAllowAddConfigurationAsOption() - { - $transport = new DsnTransportFactory([]); - $tb = new TreeBuilder(); - $rootNode = $tb->root('foo'); - - $transport->addConfiguration($rootNode); - $processor = new Processor(); - $config = $processor->process($tb->buildTree(), [['dsn' => 'amqp://example.com']]); - - $this->assertEquals(['dsn' => 'amqp://example.com'], $config); - } - - public function testThrowIfSchemeNotParsedOnCreateConnectionFactory() - { - $transport = new DsnTransportFactory([]); - - $this->expectException(\LogicException::class); - $this->expectExceptionMessage('The scheme could not be parsed from DSN "invalidDsn"'); - - $transport->createConnectionFactory(new ContainerBuilder(), ['dsn' => 'invalidDsn']); - } - - public function testThrowIfSchemeNotSupportedOnCreateConnectionFactory() - { - $transport = new DsnTransportFactory([]); - - $this->expectException(\LogicException::class); - $this->expectExceptionMessage('The scheme "http" is not supported.'); - - $transport->createConnectionFactory(new ContainerBuilder(), ['dsn' => 'http://foo.bar']); - } - - public function testThrowIfThereIsFactoryRegistered() - { - $transport = new DsnTransportFactory([ - $this->createTransportFactoryStub('foo'), - $this->createTransportFactoryStub('bar'), - ]); - - $this->expectException(\LogicException::class); - $this->expectExceptionMessage('There is no factory that supports requested schema "amqp", available are "foo", "bar"'); - - $transport->createConnectionFactory(new ContainerBuilder(), ['dsn' => 'amqp://foo']); - } - - public function testShouldProxyCallToInternalFactoryCreateConnectionFactoryMethod() - { - $container = new ContainerBuilder(); - - $internalFactory = $this->createTransportFactoryStub('amqp'); - $internalFactory - ->expects($this->once()) - ->method('createConnectionFactory') - ->with($this->identicalTo($container), ['dsn' => 'amqp://example.com']) - ->willReturn('theServiceId') - ; - - $transport = new DsnTransportFactory([$internalFactory]); - - $serviceId = $transport->createConnectionFactory($container, ['dsn' => 'amqp://example.com']); - - $this->assertEquals('theServiceId', $serviceId); - } - - public function testShouldProxyCallToInternalCreateContextMethod() - { - $container = new ContainerBuilder(); - - $internalFactory = $this->createTransportFactoryStub('amqp'); - $internalFactory - ->expects($this->once()) - ->method('createContext') - ->with($this->identicalTo($container), ['dsn' => 'amqp://example.com']) - ->willReturn('theServiceId') - ; - - $transport = new DsnTransportFactory([$internalFactory]); - - $serviceId = $transport->createContext($container, ['dsn' => 'amqp://example.com']); - - $this->assertEquals('theServiceId', $serviceId); - } - - public function testShouldProxyCallToInternalCreateDriverMethod() - { - $container = new ContainerBuilder(); - - $internalFactory = $this->createTransportFactoryStub('amqp'); - $internalFactory - ->expects($this->once()) - ->method('createDriver') - ->with($this->identicalTo($container), ['dsn' => 'amqp://example.com']) - ->willReturn('theServiceId') - ; - - $transport = new DsnTransportFactory([$internalFactory]); - - $serviceId = $transport->createDriver($container, ['dsn' => 'amqp://example.com']); - - $this->assertEquals('theServiceId', $serviceId); - } - - /** - * @param mixed $name - * - * @return \PHPUnit_Framework_MockObject_MockObject|TransportFactoryInterface - */ - private function createTransportFactoryStub($name) - { - $factoryMock = $this->createMock(TransportFactoryInterface::class); - $factoryMock - ->expects($this->any()) - ->method('getName') - ->willReturn($name) - ; - - return $factoryMock; - } -} diff --git a/pkg/null/Symfony/NullTransportFactory.php b/pkg/null/Symfony/NullTransportFactory.php index 863489b0e..b18d38474 100644 --- a/pkg/null/Symfony/NullTransportFactory.php +++ b/pkg/null/Symfony/NullTransportFactory.php @@ -31,16 +31,6 @@ public function __construct($name = 'null') */ public function addConfiguration(ArrayNodeDefinition $builder) { - $builder - ->beforeNormalization() - ->ifString()->then(function ($v) { - return ['dsn' => $v]; - }) - ->end() - ->children() - ->scalarNode('dsn')->end() - ->end() - ; } /** diff --git a/pkg/null/Tests/Symfony/NullTransportFactoryTest.php b/pkg/null/Tests/Symfony/NullTransportFactoryTest.php index 96c2ddf0d..07ee32973 100644 --- a/pkg/null/Tests/Symfony/NullTransportFactoryTest.php +++ b/pkg/null/Tests/Symfony/NullTransportFactoryTest.php @@ -50,32 +50,6 @@ public function testShouldAllowAddConfiguration() $this->assertEquals([], $config); } - public function testShouldAllowAddConfigurationWithDsnString() - { - $transport = new NullTransportFactory(); - $tb = new TreeBuilder(); - $rootNode = $tb->root('foo'); - - $transport->addConfiguration($rootNode); - $processor = new Processor(); - $config = $processor->process($tb->buildTree(), ['aStringDSN']); - - $this->assertEquals(['dsn' => 'aStringDSN'], $config); - } - - public function testShouldAllowAddConfigurationWithDsnStringOption() - { - $transport = new NullTransportFactory(); - $tb = new TreeBuilder(); - $rootNode = $tb->root('foo'); - - $transport->addConfiguration($rootNode); - $processor = new Processor(); - $config = $processor->process($tb->buildTree(), [['dsn' => 'aStringDSN']]); - - $this->assertEquals(['dsn' => 'aStringDSN'], $config); - } - public function testShouldCreateConnectionFactory() { $container = new ContainerBuilder(); From 875f1ba32a335b49b32d024f51c4b2d1bcf68838 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 12 May 2017 22:40:51 +0300 Subject: [PATCH 5/5] [amqp] fixes --- docker-compose.yml | 1 + pkg/amqp-ext/AmqpConnectionFactory.php | 19 +- .../Tests/Functional/UseCasesTest.php | 211 +++++++++--------- .../DependencyInjection/ConfigurationTest.php | 28 +-- .../Symfony/DefaultTransportFactoryTest.php | 25 ++- pkg/null/Symfony/NullTransportFactory.php | 10 + .../Symfony/NullTransportFactoryTest.php | 32 ++- pkg/test/RabbitmqAmqpExtension.php | 12 + 8 files changed, 208 insertions(+), 130 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8a55a7ea0..459ac5c46 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: volumes: - './:/mqdev' environment: + - AMQP_DSN=amqp://rabbitmq - SYMFONY__RABBITMQ__HOST=rabbitmq - SYMFONY__RABBITMQ__USER=guest - SYMFONY__RABBITMQ__PASSWORD=guest diff --git a/pkg/amqp-ext/AmqpConnectionFactory.php b/pkg/amqp-ext/AmqpConnectionFactory.php index e168cf796..46b46ed65 100644 --- a/pkg/amqp-ext/AmqpConnectionFactory.php +++ b/pkg/amqp-ext/AmqpConnectionFactory.php @@ -17,7 +17,7 @@ class AmqpConnectionFactory implements PsrConnectionFactory private $connection; /** - * The config could be an array, string DSN or null. In case of null it will attempt to connect to localhost with default credentials + * The config could be an array, string DSN or null. In case of null it will attempt to connect to localhost with default credentials. * * [ * 'host' => amqp.host The host to connect too. Note: Max 1024 characters. @@ -42,9 +42,9 @@ public function __construct($config = 'amqp://') { if (empty($config)) { $config = []; - } else if (is_string($config)) { + } elseif (is_string($config)) { $config = $this->parseDsn($config); - } else if (is_array($config)) { + } elseif (is_array($config)) { } else { throw new \LogicException('The config must be eaither an array of options, a DSN string or null'); } @@ -68,14 +68,18 @@ public function createContext() return new AmqpContext(new \AMQPChannel($this->establishConnection())); } + /** + * @return \AMQPConnection + */ private function establishConnection() { if (false == $this->connection) { - $this->connection = new \AMQPConnection($this->config); - + $config = $this->config; + $config['login'] = $this->config['user']; + $config['password'] = $this->config['pass']; + $this->connection = new \AMQPConnection($config); $this->config['persisted'] ? $this->connection->pconnect() : $this->connection->connect(); } - if (false == $this->connection->isConnected()) { $this->config['persisted'] ? $this->connection->preconnect() : $this->connection->reconnect(); } @@ -123,9 +127,8 @@ private function parseDsn($dsn) unset($dsnConfig['scheme'], $dsnConfig['query'], $dsnConfig['fragment'], $dsnConfig['path']); - $config = array_replace($this->defaultConfig(), $dsnConfig); - $config = array_map(function($value) { + $config = array_map(function ($value) { return urldecode($value); }, $config); diff --git a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php index 502752e53..d5e8f9986 100644 --- a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php +++ b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php @@ -14,89 +14,106 @@ */ class UseCasesTest extends WebTestCase { + public function setUp() + { + // do not call parent::setUp. + // parent::setUp(); + } + public function provideEnqueueConfigs() { - return [ - ['amqp' => [ - 'transport' => [ - 'default' => 'amqp', - 'amqp' => [ - 'host' => getenv('SYMFONY__RABBITMQ__HOST'), - 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), - 'user' => getenv('SYMFONY__RABBITMQ__USER'), - 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), - 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), - 'lazy' => false, - ] - ] - ]], - ['stomp' => [ - 'transport' => [ - 'default' => 'stomp', - 'stomp' => [ - 'host' => getenv('SYMFONY__RABBITMQ__HOST'), - 'port' => getenv('SYMFONY__RABBITMQ__STOMP__PORT'), - 'login' => getenv('SYMFONY__RABBITMQ__USER'), - 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), - 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), - 'lazy' => false, - ] - ] - ]], - ['predis' => [ - 'transport' => [ - 'default' => 'redis', - 'redis' => [ - 'host' => getenv('SYMFONY__REDIS__HOST'), - 'port' => (int) getenv('SYMFONY__REDIS__PORT'), - 'vendor' => 'predis', - 'lazy' => false, - ] - ] - ]], - ['phpredis' => [ - 'transport' => [ - 'default' => 'redis', - 'redis' => [ - 'host' => getenv('SYMFONY__REDIS__HOST'), - 'port' => (int) getenv('SYMFONY__REDIS__PORT'), - 'vendor' => 'phpredis', - 'lazy' => false, - ] - ] - ]], - ['fs' => [ - 'transport' => [ - 'default' => 'fs', - 'fs' => [ - 'store_dir' => sys_get_temp_dir(), - ] - ] - ]], - ['dbal' => [ - 'transport' => [ - 'default' => 'dbal', - 'dbal' => [ - 'dbname' => getenv('SYMFONY__DB__NAME'), - 'user' => getenv('SYMFONY__DB__USER'), - 'password' => getenv('SYMFONY__DB__PASSWORD'), - 'host' => getenv('SYMFONY__DB__HOST'), - 'port' => getenv('SYMFONY__DB__PORT'), - 'driver' => getenv('SYMFONY__DB__DRIVER'), - ] - ] - ]], - ['sqs' => [ - 'transport' => [ - 'default' => 'sqs', - 'sqs' => [ - 'key' => getenv('AWS__SQS__KEY'), - 'secret' => getenv('AWS__SQS__SECRET'), - 'region' => getenv('AWS__SQS__REGION'), - ] - ] - ]], - ]; + yield 'amqp' => [[ + 'transport' => [ + 'default' => 'amqp', + 'amqp' => [ + 'host' => getenv('SYMFONY__RABBITMQ__HOST'), + 'port' => getenv('SYMFONY__RABBITMQ__AMQP__PORT'), + 'user' => getenv('SYMFONY__RABBITMQ__USER'), + 'pass' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), + 'lazy' => false, + ], + ], + ]]; + + yield 'amqp_dsn' => [[ + 'transport' => [ + 'default' => 'amqp', + 'amqp' => getenv('AMQP_DSN'), + ], + ]]; + + yield 'stomp' => [[ + 'transport' => [ + 'default' => 'stomp', + 'stomp' => [ + 'host' => getenv('SYMFONY__RABBITMQ__HOST'), + 'port' => getenv('SYMFONY__RABBITMQ__STOMP__PORT'), + 'login' => getenv('SYMFONY__RABBITMQ__USER'), + 'password' => getenv('SYMFONY__RABBITMQ__PASSWORD'), + 'vhost' => getenv('SYMFONY__RABBITMQ__VHOST'), + 'lazy' => false, + ], + ], + ]]; + + yield 'predis' => [[ + 'transport' => [ + 'default' => 'redis', + 'redis' => [ + 'host' => getenv('SYMFONY__REDIS__HOST'), + 'port' => (int) getenv('SYMFONY__REDIS__PORT'), + 'vendor' => 'predis', + 'lazy' => false, + ], + ], + ]]; + + yield 'phpredis' => [[ + 'transport' => [ + 'default' => 'redis', + 'redis' => [ + 'host' => getenv('SYMFONY__REDIS__HOST'), + 'port' => (int) getenv('SYMFONY__REDIS__PORT'), + 'vendor' => 'phpredis', + 'lazy' => false, + ], + ], + ]]; + + yield 'fs' => [[ + 'transport' => [ + 'default' => 'fs', + 'fs' => [ + 'store_dir' => sys_get_temp_dir(), + ], + ], + ]]; + + yield 'dbal' => [[ + 'transport' => [ + 'default' => 'dbal', + 'dbal' => [ + 'dbname' => getenv('SYMFONY__DB__NAME'), + 'user' => getenv('SYMFONY__DB__USER'), + 'password' => getenv('SYMFONY__DB__PASSWORD'), + 'host' => getenv('SYMFONY__DB__HOST'), + 'port' => getenv('SYMFONY__DB__PORT'), + 'driver' => getenv('SYMFONY__DB__DRIVER'), + ], + ], + ]]; + + yield 'sqs' => [[ + 'transport' => [ + 'default' => 'sqs', + 'sqs' => [ + 'key' => getenv('AWS__SQS__KEY'), + 'secret' => getenv('AWS__SQS__SECRET'), + 'region' => getenv('AWS__SQS__REGION'), + ], + ], + ]]; } /** @@ -167,19 +184,13 @@ public function testTransportConsumeMessagesCommandShouldConsumeMessage(array $e } /** - * @return ProducerInterface|object + * @return string */ - private function getMessageProducer() + public static function getKernelClass() { - return $this->container->get('enqueue.client.producer'); - } + include_once __DIR__.'/app/CustomAppKernel.php'; - /** - * @return PsrContext|object - */ - private function getPsrContext() - { - return $this->container->get('enqueue.transport.context'); + return CustomAppKernel::class; } protected function customSetUp(array $enqueueConfig) @@ -209,7 +220,7 @@ protected function customSetUp(array $enqueueConfig) /** * {@inheritdoc} */ - protected static function createKernel(array $options = array()) + protected static function createKernel(array $options = []) { /** @var CustomAppKernel $kernel */ $kernel = parent::createKernel($options); @@ -220,18 +231,18 @@ protected static function createKernel(array $options = array()) } /** - * @return string + * @return ProducerInterface|object */ - public static function getKernelClass() + private function getMessageProducer() { - include_once __DIR__.'/app/CustomAppKernel.php'; - - return CustomAppKernel::class; + return $this->container->get('enqueue.client.producer'); } - public function setUp() + /** + * @return PsrContext|object + */ + private function getPsrContext() { - // do not call parent::setUp. - // parent::setUp(); + return $this->container->get('enqueue.transport.context'); } } diff --git a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php index 0ae61b208..61a1999c7 100644 --- a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php @@ -4,13 +4,13 @@ use Enqueue\Bundle\DependencyInjection\Configuration; use Enqueue\Bundle\Tests\Unit\Mocks\FooTransportFactory; -use Enqueue\Symfony\DefaultTransportFactory; use Enqueue\Null\Symfony\NullTransportFactory; +use Enqueue\Symfony\DefaultTransportFactory; use Enqueue\Test\ClassExtensionTrait; +use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Processor; -use PHPUnit\Framework\TestCase; class ConfigurationTest extends TestCase { @@ -28,10 +28,8 @@ public function testCouldBeConstructedWithFactoriesAsFirstArgument() public function testThrowIfTransportNotConfigured() { - $this->setExpectedException( - InvalidConfigurationException::class, - 'The child node "transport" at path "enqueue" must be configured.' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The child node "transport" at path "enqueue" must be configured.'); $configuration = new Configuration([]); @@ -59,10 +57,8 @@ public function testThrowExceptionIfFooTransportConfigInvalid() $processor = new Processor(); - $this->setExpectedException( - InvalidConfigurationException::class, - 'The path "enqueue.transport.foo.foo_param" cannot contain an empty value, but got null.' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The path "enqueue.transport.foo.foo_param" cannot contain an empty value, but got null.'); $processor->processConfiguration($configuration, [[ 'transport' => [ @@ -160,10 +156,8 @@ public function testShouldSetDefaultConfigurationForClient() public function testThrowExceptionIfRouterTopicIsEmpty() { - $this->setExpectedException( - InvalidConfigurationException::class, - 'The path "enqueue.client.router_topic" cannot contain an empty value, but got "".' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The path "enqueue.client.router_topic" cannot contain an empty value, but got "".'); $configuration = new Configuration([new DefaultTransportFactory()]); @@ -180,10 +174,8 @@ public function testThrowExceptionIfRouterTopicIsEmpty() public function testThrowExceptionIfRouterQueueIsEmpty() { - $this->setExpectedException( - InvalidConfigurationException::class, - 'The path "enqueue.client.router_queue" cannot contain an empty value, but got "".' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The path "enqueue.client.router_queue" cannot contain an empty value, but got "".'); $configuration = new Configuration([new DefaultTransportFactory()]); diff --git a/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php b/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php index 39cdca9c2..610727e37 100644 --- a/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php +++ b/pkg/enqueue/Tests/Symfony/DefaultTransportFactoryTest.php @@ -5,10 +5,10 @@ use Enqueue\Symfony\DefaultTransportFactory; use Enqueue\Symfony\TransportFactoryInterface; use Enqueue\Test\ClassExtensionTrait; +use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\DependencyInjection\ContainerBuilder; -use PHPUnit\Framework\TestCase; class DefaultTransportFactoryTest extends TestCase { @@ -46,6 +46,29 @@ public function testShouldAllowAddConfiguration() $this->assertEquals(['alias' => 'the_alias'], $config); } + public function testShouldCreateConnectionFactory() + { + $container = new ContainerBuilder(); + + $transport = new DefaultTransportFactory(); + + $serviceId = $transport->createConnectionFactory($container, ['alias' => 'foo']); + + $this->assertEquals('enqueue.transport.default.connection_factory', $serviceId); + + $this->assertTrue($container->hasAlias('enqueue.transport.default.connection_factory')); + $this->assertEquals( + 'enqueue.transport.foo.connection_factory', + (string) $container->getAlias('enqueue.transport.default.connection_factory') + ); + + $this->assertTrue($container->hasAlias('enqueue.transport.connection_factory')); + $this->assertEquals( + 'enqueue.transport.default.connection_factory', + (string) $container->getAlias('enqueue.transport.connection_factory') + ); + } + public function testShouldCreateContext() { $container = new ContainerBuilder(); diff --git a/pkg/null/Symfony/NullTransportFactory.php b/pkg/null/Symfony/NullTransportFactory.php index b18d38474..863489b0e 100644 --- a/pkg/null/Symfony/NullTransportFactory.php +++ b/pkg/null/Symfony/NullTransportFactory.php @@ -31,6 +31,16 @@ public function __construct($name = 'null') */ public function addConfiguration(ArrayNodeDefinition $builder) { + $builder + ->beforeNormalization() + ->ifString()->then(function ($v) { + return ['dsn' => $v]; + }) + ->end() + ->children() + ->scalarNode('dsn')->end() + ->end() + ; } /** diff --git a/pkg/null/Tests/Symfony/NullTransportFactoryTest.php b/pkg/null/Tests/Symfony/NullTransportFactoryTest.php index 07ee32973..b6c80f154 100644 --- a/pkg/null/Tests/Symfony/NullTransportFactoryTest.php +++ b/pkg/null/Tests/Symfony/NullTransportFactoryTest.php @@ -3,16 +3,16 @@ namespace Enqueue\Null\Tests\Symfony; use Enqueue\Null\Client\NullDriver; +use Enqueue\Null\NullConnectionFactory; +use Enqueue\Null\NullContext; use Enqueue\Null\Symfony\NullTransportFactory; use Enqueue\Symfony\TransportFactoryInterface; use Enqueue\Test\ClassExtensionTrait; -use Enqueue\Null\NullConnectionFactory; -use Enqueue\Null\NullContext; +use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; -use PHPUnit\Framework\TestCase; class NullTransportFactoryTest extends TestCase { @@ -50,6 +50,32 @@ public function testShouldAllowAddConfiguration() $this->assertEquals([], $config); } + public function testShouldAllowAddConfigurationWithDsnString() + { + $transport = new NullTransportFactory(); + $tb = new TreeBuilder(); + $rootNode = $tb->root('foo'); + + $transport->addConfiguration($rootNode); + $processor = new Processor(); + $config = $processor->process($tb->buildTree(), ['aStringDSN']); + + $this->assertEquals(['dsn' => 'aStringDSN'], $config); + } + + public function testShouldAllowAddConfigurationWithDsnStringOption() + { + $transport = new NullTransportFactory(); + $tb = new TreeBuilder(); + $rootNode = $tb->root('foo'); + + $transport->addConfiguration($rootNode); + $processor = new Processor(); + $config = $processor->process($tb->buildTree(), [['dsn' => 'aStringDSN']]); + + $this->assertEquals(['dsn' => 'aStringDSN'], $config); + } + public function testShouldCreateConnectionFactory() { $container = new ContainerBuilder(); diff --git a/pkg/test/RabbitmqAmqpExtension.php b/pkg/test/RabbitmqAmqpExtension.php index 480f99626..ad698fcfe 100644 --- a/pkg/test/RabbitmqAmqpExtension.php +++ b/pkg/test/RabbitmqAmqpExtension.php @@ -26,4 +26,16 @@ private function buildAmqpContext() return (new AmqpConnectionFactory($config))->createContext(); } + + /** + * @return AmqpContext + */ + private function buildAmqpContextFromDsn() + { + if (false == $dsn = getenv('AMQP_DSN')) { + throw new \PHPUnit_Framework_SkippedTestError('Functional tests are not allowed in this environment'); + } + + return (new AmqpConnectionFactory($dsn))->createContext(); + } }