Skip to content

Commit

Permalink
Introduce TracingDriverForV32 for DBAL >= 3.2 (#723)
Browse files Browse the repository at this point in the history
  • Loading branch information
ruudk committed Jun 12, 2023
1 parent a39c362 commit 7d73be0
Show file tree
Hide file tree
Showing 11 changed files with 247 additions and 6 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
- 6.*
dependencies:
- highest
doctrine-dbal:
- highest
exclude:
- php: '7.2'
symfony-version: 6.*
Expand All @@ -41,12 +43,18 @@ jobs:
- php: '7.2'
symfony-version: 4.4.*
dependencies: lowest
doctrine-dbal: '^2.13'
- php: '7.2'
symfony-version: 5.*
dependencies: lowest
doctrine-dbal: '^2.13'
- php: '8.0'
symfony-version: 6.*
dependencies: lowest
doctrine-dbal: '^2.13'
- php: '8.0'
symfony-version: 6.*
doctrine-dbal: '<3.2'

steps:
- name: Checkout
Expand All @@ -68,6 +76,10 @@ jobs:
run: composer require --dev phpunit/phpunit ^9.3.9 --no-update
if: matrix.php == '8.0' && matrix.dependencies == 'lowest'

- name: Update Doctrine DBAL
run: composer require --dev doctrine/dbal "${{ matrix.doctrine-dbal }}" --no-update
if: matrix.doctrine-dbal != 'highest'

- name: Install dependencies
uses: ramsey/composer-install@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"require-dev": {
"doctrine/dbal": "^2.13||^3.0",
"doctrine/doctrine-bundle": "^1.12||^2.5",
"friendsofphp/php-cs-fixer": "^2.19||^3.6",
"friendsofphp/php-cs-fixer": "^2.19||<=3.16.0",
"jangregor/phpstan-prophecy": "^1.0",
"monolog/monolog": "^1.3||^2.0",
"phpspec/prophecy": "!=1.11.0",
Expand Down
2 changes: 1 addition & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ parameters:
path: src/Tracing/Doctrine/DBAL/TracingServerInfoAwareDriverConnection.php

-
message: "#^Parameter \\#2 \\$callback of method Sentry\\\\SentryBundle\\\\Tracing\\\\Doctrine\\\\DBAL\\\\AbstractTracingStatement\\:\\:traceFunction\\(\\) expects callable\\(\\.\\.\\.mixed\\)\\: Doctrine\\\\DBAL\\\\Driver\\\\Result, array\\{Doctrine\\\\DBAL\\\\Driver\\\\Statement, 'execute'\\} given\\.$#"
message: "#^Parameter \\#2 \\$callback of method Sentry\\\\SentryBundle\\\\Tracing\\\\Doctrine\\\\DBAL\\\\AbstractTracingStatement\\:\\:traceFunction\\(\\) expects callable\\(mixed \\.\\.\\.\\)\\: Doctrine\\\\DBAL\\\\Driver\\\\Result, array\\{Doctrine\\\\DBAL\\\\Driver\\\\Statement, 'execute'\\} given\\.$#"
count: 1
path: src/Tracing/Doctrine/DBAL/TracingStatementForV3.php

Expand Down
11 changes: 11 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@
<code>$params</code>
</MoreSpecificImplementedParamType>
</file>
<file src="src/Tracing/Doctrine/DBAL/TracingDriverForV32.php">
<InvalidReturnStatement occurrences="1">
<code>$this-&gt;decoratedDriver-&gt;getSchemaManager($conn, $platform)</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="1">
<code>AbstractSchemaManager&lt;T&gt;</code>
</InvalidReturnType>
<MoreSpecificImplementedParamType occurrences="1">
<code>$params</code>
</MoreSpecificImplementedParamType>
</file>
<file src="src/Tracing/HttpClient/TraceableResponseForV5.php">
<UndefinedInterfaceMethod occurrences="1">
<code>toStream</code>
Expand Down
89 changes: 89 additions & 0 deletions src/Tracing/Doctrine/DBAL/TracingDriverForV32.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

namespace Sentry\SentryBundle\Tracing\Doctrine\DBAL;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;

/**
* This is a simple implementation of the {@see Driver} interface that decorates
* an existing driver to support distributed tracing capabilities. This implementation
* is compatible with all versions of Doctrine DBAL >= 3.2.
*
* @internal
*
* @phpstan-import-type Params from \Doctrine\DBAL\DriverManager as ConnectionParams
*/
final class TracingDriverForV32 implements Driver
{
/**
* @var TracingDriverConnectionFactoryInterface The connection factory
*/
private $connectionFactory;

/**
* @var Driver The instance of the decorated driver
*/
private $decoratedDriver;

/**
* Constructor.
*
* @param TracingDriverConnectionFactoryInterface $connectionFactory The connection factory
* @param Driver $decoratedDriver The instance of the driver to decorate
*/
public function __construct(TracingDriverConnectionFactoryInterface $connectionFactory, Driver $decoratedDriver)
{
$this->connectionFactory = $connectionFactory;
$this->decoratedDriver = $decoratedDriver;
}

/**
* {@inheritdoc}
*
* @phpstan-param ConnectionParams $params
*/
public function connect(array $params): TracingDriverConnectionInterface
{
return $this->connectionFactory->create(
$this->decoratedDriver->connect($params),
$this->decoratedDriver->getDatabasePlatform(),
$params
);
}

/**
* {@inheritdoc}
*/
public function getDatabasePlatform(): AbstractPlatform
{
return $this->decoratedDriver->getDatabasePlatform();
}

/**
* {@inheritdoc}
*
* @phpstan-template T of AbstractPlatform
*
* @phpstan-param T $platform
*
* @phpstan-return AbstractSchemaManager<T>
*/
public function getSchemaManager(Connection $conn, AbstractPlatform $platform): AbstractSchemaManager
{
return $this->decoratedDriver->getSchemaManager($conn, $platform);
}

/**
* {@inheritdoc}
*/
public function getExceptionConverter(): ExceptionConverter
{
return $this->decoratedDriver->getExceptionConverter();
}
}
9 changes: 8 additions & 1 deletion src/aliases.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Sentry\SentryBundle;

use Doctrine\DBAL\Exception\SchemaDoesNotExist;
use Doctrine\DBAL\Result;
use Sentry\SentryBundle\Tracing\Cache\TraceableCacheAdapter;
use Sentry\SentryBundle\Tracing\Cache\TraceableCacheAdapterForV2;
Expand All @@ -14,6 +15,7 @@
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriver;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV2;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV3;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV32;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatement;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatementForV2;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatementForV3;
Expand Down Expand Up @@ -53,7 +55,12 @@ class_alias(TraceableTagAwareCacheAdapterForV2::class, TraceableTagAwareCacheAda
if (!class_exists(TracingStatement::class)) {
if (class_exists(Result::class)) {
class_alias(TracingStatementForV3::class, TracingStatement::class);
class_alias(TracingDriverForV3::class, TracingDriver::class);

if (class_exists(SchemaDoesNotExist::class)) {
class_alias(TracingDriverForV32::class, TracingDriver::class);
} else {
class_alias(TracingDriverForV3::class, TracingDriver::class);
}
} elseif (interface_exists(Result::class)) {
class_alias(TracingStatementForV2::class, TracingStatement::class);
class_alias(TracingDriverForV2::class, TracingDriver::class);
Expand Down
7 changes: 7 additions & 0 deletions tests/DoctrineTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Exception\SchemaDoesNotExist;
use PHPUnit\Framework\TestCase;

abstract class DoctrineTestCase extends TestCase
Expand All @@ -28,6 +29,12 @@ protected static function isDoctrineDBALVersion3Installed(): bool
&& !self::isDoctrineDBALVersion2Installed();
}

protected static function isDoctrineDBALVersion32Installed(): bool
{
return self::isDoctrineDBALInstalled()
&& class_exists(SchemaDoesNotExist::class);
}

protected static function isDoctrineBundlePackageInstalled(): bool
{
return class_exists(DoctrineBundle::class);
Expand Down
2 changes: 1 addition & 1 deletion tests/End2End/App/Command/MainCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class MainCommand extends Command
{
protected function configure()
protected function configure(): void
{
$this
->addOption('option1', null, InputOption::VALUE_NONE)
Expand Down
112 changes: 112 additions & 0 deletions tests/Tracing/Doctrine/DBAL/TracingDriverForV32Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

declare(strict_types=1);

namespace Sentry\SentryBundle\Tests\Tracing\Doctrine\DBAL;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Driver as DriverInterface;
use Doctrine\DBAL\Driver\Connection as DriverConnectionInterface;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use PHPUnit\Framework\MockObject\MockObject;
use Sentry\SentryBundle\Tests\DoctrineTestCase;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverConnectionFactoryInterface;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverConnectionInterface;
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV32;

final class TracingDriverForV32Test extends DoctrineTestCase
{
/**
* @var MockObject&TracingDriverConnectionFactoryInterface
*/
private $connectionFactory;

public static function setUpBeforeClass(): void
{
if (!self::isDoctrineDBALVersion32Installed()) {
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.2.');
}
}

protected function setUp(): void
{
$this->connectionFactory = $this->createMock(TracingDriverConnectionFactoryInterface::class);
}

public function testConnect(): void
{
$params = ['host' => 'localhost'];
$databasePlatform = $this->createMock(AbstractPlatform::class);
$driverConnection = $this->createMock(DriverConnectionInterface::class);
$tracingDriverConnection = $this->createMock(TracingDriverConnectionInterface::class);
$decoratedDriver = $this->createMock(DriverInterface::class);

$decoratedDriver->expects($this->once())
->method('connect')
->with($params)
->willReturn($driverConnection);

$decoratedDriver->expects($this->once())
->method('getDatabasePlatform')
->willReturn($databasePlatform);

$this->connectionFactory->expects($this->once())
->method('create')
->with($driverConnection, $databasePlatform, $params)
->willReturn($tracingDriverConnection);

$driver = new TracingDriverForV32($this->connectionFactory, $decoratedDriver);

$this->assertSame($tracingDriverConnection, $driver->connect($params));
}

public function testGetDatabasePlatform(): void
{
$databasePlatform = $this->createMock(AbstractPlatform::class);

$decoratedDriver = $this->createMock(DriverInterface::class);
$decoratedDriver->expects($this->once())
->method('getDatabasePlatform')
->willReturn($databasePlatform);

$driver = new TracingDriverForV32($this->connectionFactory, $decoratedDriver);

$this->assertSame($databasePlatform, $driver->getDatabasePlatform());
}

/**
* @group legacy
*/
public function testGetSchemaManager(): void
{
$connection = $this->createMock(Connection::class);
$databasePlatform = $this->createMock(AbstractPlatform::class);
$schemaManager = $this->createMock(AbstractSchemaManager::class);

$decoratedDriver = $this->createMock(DriverInterface::class);
$decoratedDriver->expects($this->once())
->method('getSchemaManager')
->with($connection, $databasePlatform)
->willReturn($schemaManager);

$driver = new TracingDriverForV32($this->connectionFactory, $decoratedDriver);

$this->assertSame($schemaManager, $driver->getSchemaManager($connection, $databasePlatform));
}

public function testGetExceptionConverter(): void
{
$exceptionConverter = $this->createMock(ExceptionConverter::class);

$decoratedDriver = $this->createMock(DriverInterface::class);
$decoratedDriver->expects($this->once())
->method('getExceptionConverter')
->willReturn($exceptionConverter);

$driver = new TracingDriverForV32($this->connectionFactory, $decoratedDriver);

$this->assertSame($exceptionConverter, $driver->getExceptionConverter());
}
}
4 changes: 2 additions & 2 deletions tests/Tracing/Doctrine/DBAL/TracingDriverForV3Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ final class TracingDriverForV3Test extends DoctrineTestCase

public static function setUpBeforeClass(): void
{
if (!self::isDoctrineDBALVersion3Installed()) {
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.0.');
if (!self::isDoctrineDBALVersion3Installed() || self::isDoctrineDBALVersion32Installed()) {
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.0 <= 3.2.');
}
}

Expand Down
3 changes: 3 additions & 0 deletions tests/Tracing/Doctrine/DBAL/TracingStatementForV3Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public function testBindValue(): void
$this->assertTrue($this->statement->bindValue('foo', 'bar', ParameterType::INTEGER));
}

/**
* @group legacy
*/
public function testBindParam(): void
{
$variable = 'bar';
Expand Down

0 comments on commit 7d73be0

Please sign in to comment.