Failed Conditions
Pull Request — master (#3260)
by Michael
61:30
created

AbstractDriverTest.php$0 ➔ testConvertsException()   A

Complexity

Conditions 2

Size

Total Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 49
rs 9.1127
c 0
b 0
f 0
cc 2

2 Methods

Rating   Name   Duplication   Size   Complexity  
A AbstractDriverTest.php$0 ➔ __construct() 0 3 1
A AbstractDriverTest.php$0 ➔ getSQLState() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\DBAL\Driver;
6
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\DBALException;
9
use Doctrine\DBAL\Driver;
10
use Doctrine\DBAL\Driver\DriverException as DriverExceptionInterface;
11
use Doctrine\DBAL\Driver\ExceptionConverterDriver;
12
use Doctrine\DBAL\Exception\ConnectionException;
13
use Doctrine\DBAL\Exception\ConstraintViolationException;
14
use Doctrine\DBAL\Exception\DatabaseObjectExistsException;
15
use Doctrine\DBAL\Exception\DatabaseObjectNotFoundException;
16
use Doctrine\DBAL\Exception\DeadlockException;
17
use Doctrine\DBAL\Exception\DriverException;
18
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
19
use Doctrine\DBAL\Exception\InvalidFieldNameException;
20
use Doctrine\DBAL\Exception\LockWaitTimeoutException;
21
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
22
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
23
use Doctrine\DBAL\Exception\ReadOnlyException;
24
use Doctrine\DBAL\Exception\ServerException;
25
use Doctrine\DBAL\Exception\SyntaxErrorException;
26
use Doctrine\DBAL\Exception\TableExistsException;
27
use Doctrine\DBAL\Exception\TableNotFoundException;
28
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
29
use Doctrine\DBAL\Platforms\AbstractPlatform;
30
use Doctrine\DBAL\Schema\AbstractSchemaManager;
31
use Doctrine\DBAL\VersionAwarePlatformDriver;
32
use Doctrine\Tests\DbalTestCase;
33
use Exception;
34
use ReflectionProperty;
35
use function get_class;
36
use function sprintf;
37
38
abstract class AbstractDriverTest extends DbalTestCase
39
{
40
    public const EXCEPTION_CONNECTION                       = ConnectionException::class;
41
    public const EXCEPTION_CONSTRAINT_VIOLATION             = ConstraintViolationException::class;
42
    public const EXCEPTION_DATABASE_OBJECT_EXISTS           = DatabaseObjectExistsException::class;
43
    public const EXCEPTION_DATABASE_OBJECT_NOT_FOUND        = DatabaseObjectNotFoundException::class;
44
    public const EXCEPTION_DRIVER                           = DriverException::class;
45
    public const EXCEPTION_FOREIGN_KEY_CONSTRAINT_VIOLATION = ForeignKeyConstraintViolationException::class;
46
    public const EXCEPTION_INVALID_FIELD_NAME               = InvalidFieldNameException::class;
47
    public const EXCEPTION_NON_UNIQUE_FIELD_NAME            = NonUniqueFieldNameException::class;
48
    public const EXCEPTION_NOT_NULL_CONSTRAINT_VIOLATION    = NotNullConstraintViolationException::class;
49
    public const EXCEPTION_READ_ONLY                        = ReadOnlyException::class;
50
    public const EXCEPTION_SERVER                           = ServerException::class;
51
    public const EXCEPTION_SYNTAX_ERROR                     = SyntaxErrorException::class;
52
    public const EXCEPTION_TABLE_EXISTS                     = TableExistsException::class;
53
    public const EXCEPTION_TABLE_NOT_FOUND                  = TableNotFoundException::class;
54
    public const EXCEPTION_UNIQUE_CONSTRAINT_VIOLATION      = UniqueConstraintViolationException::class;
55
    public const EXCEPTION_DEADLOCK                         = DeadlockException::class;
56
    public const EXCEPTION_LOCK_WAIT_TIMEOUT                = LockWaitTimeoutException::class;
57
58
    /**
59
     * The driver mock under test.
60
     *
61
     * @var Driver
62
     */
63
    protected $driver;
64
65
    protected function setUp() : void
66
    {
67
        parent::setUp();
68
69
        $this->driver = $this->createDriver();
70
    }
71
72
    public function testConvertsException()
73
    {
74
        if (! $this->driver instanceof ExceptionConverterDriver) {
75
            $this->markTestSkipped('This test is only intended for exception converter drivers.');
76
        }
77
78
        $data = $this->getExceptionConversions();
79
80
        if (empty($data)) {
81
            $this->fail(
82
                sprintf(
83
                    'No test data found for test %s. You have to return test data from %s.',
84
                    static::class . '::' . __FUNCTION__,
85
                    static::class . '::getExceptionConversionData'
86
                )
87
            );
88
        }
89
90
        $driverException = new class extends Exception implements DriverExceptionInterface
91
        {
92
            public function __construct()
93
            {
94
                parent::__construct('baz');
95
            }
96
97
            /**
98
             * {@inheritDoc}
99
             */
100
            public function getSQLState() : ?string
101
            {
102
                return 'bar';
103
            }
104
        };
105
106
        $data[] = [$driverException, self::EXCEPTION_DRIVER];
107
108
        $message = 'DBAL exception message';
109
110
        foreach ($data as $item) {
111
            /** @var DriverException $driverException */
112
            [$driverException, $convertedExceptionClassName] = $item;
113
114
            $convertedException = $this->driver->convertException($message, $driverException);
115
116
            self::assertSame($convertedExceptionClassName, get_class($convertedException));
117
118
            self::assertSame($driverException->getCode(), $convertedException->getCode());
119
            self::assertSame($driverException->getSQLState(), $convertedException->getSQLState());
120
            self::assertSame($message, $convertedException->getMessage());
121
        }
122
    }
123
124
    public function testCreatesDatabasePlatformForVersion()
125
    {
126
        if (! $this->driver instanceof VersionAwarePlatformDriver) {
127
            $this->markTestSkipped('This test is only intended for version aware platform drivers.');
128
        }
129
130
        $data = $this->getDatabasePlatformsForVersions();
131
132
        self::assertNotEmpty(
133
            $data,
134
            sprintf(
135
                'No test data found for test %s. You have to return test data from %s.',
136
                static::class . '::' . __FUNCTION__,
137
                static::class . '::getDatabasePlatformsForVersions'
138
            )
139
        );
140
141
        foreach ($data as $item) {
142
            $generatedVersion = get_class($this->driver->createDatabasePlatformForVersion($item[0]));
143
144
            self::assertSame(
145
                $item[1],
146
                $generatedVersion,
147
                sprintf(
148
                    'Expected platform for version "%s" should be "%s", "%s" given',
149
                    $item[0],
150
                    $item[1],
151
                    $generatedVersion
152
                )
153
            );
154
        }
155
    }
156
157
    public function testThrowsExceptionOnCreatingDatabasePlatformsForInvalidVersion()
158
    {
159
        if (! $this->driver instanceof VersionAwarePlatformDriver) {
160
            $this->markTestSkipped('This test is only intended for version aware platform drivers.');
161
        }
162
163
        $this->expectException(DBALException::class);
164
        $this->driver->createDatabasePlatformForVersion('foo');
165
    }
166
167
    public function testReturnsDatabaseName()
168
    {
169
        $params = [
170
            'user'     => 'foo',
171
            'password' => 'bar',
172
            'dbname'   => 'baz',
173
        ];
174
175
        $connection = $this->getConnectionMock();
176
177
        $connection->expects($this->once())
178
            ->method('getParams')
179
            ->will($this->returnValue($params));
180
181
        self::assertSame($params['dbname'], $this->driver->getDatabase($connection));
182
    }
183
184
    public function testReturnsDatabasePlatform()
185
    {
186
        self::assertEquals($this->createPlatform(), $this->driver->getDatabasePlatform());
187
    }
188
189
    public function testReturnsSchemaManager()
190
    {
191
        $connection    = $this->getConnectionMock();
192
        $schemaManager = $this->driver->getSchemaManager($connection);
193
194
        self::assertEquals($this->createSchemaManager($connection), $schemaManager);
195
196
        $re = new ReflectionProperty($schemaManager, '_conn');
197
        $re->setAccessible(true);
198
199
        self::assertSame($connection, $re->getValue($schemaManager));
200
    }
201
202
    /**
203
     * Factory method for creating the driver instance under test.
204
     *
205
     * @return Driver
206
     */
207
    abstract protected function createDriver();
208
209
    /**
210
     * Factory method for creating the the platform instance return by the driver under test.
211
     *
212
     * The platform instance returned by this method must be the same as returned by
213
     * the driver's getDatabasePlatform() method.
214
     *
215
     * @return AbstractPlatform
216
     */
217
    abstract protected function createPlatform();
218
219
    /**
220
     * Factory method for creating the the schema manager instance return by the driver under test.
221
     *
222
     * The schema manager instance returned by this method must be the same as returned by
223
     * the driver's getSchemaManager() method.
224
     *
225
     * @param Connection $connection The underlying connection to use.
226
     *
227
     * @return AbstractSchemaManager
228
     */
229
    abstract protected function createSchemaManager(Connection $connection);
230
231
    protected function getConnectionMock()
232
    {
233
        return $this->getMockBuilder(Connection::class)
234
            ->disableOriginalConstructor()
235
            ->getMock();
236
    }
237
238
    protected function getDatabasePlatformsForVersions()
239
    {
240
        return [];
241
    }
242
243
    protected function getExceptionConversionData()
244
    {
245
        return [];
246
    }
247
248
    private function getExceptionConversions()
249
    {
250
        $data = [];
251
252
        foreach ($this->getExceptionConversionData() as $convertedExceptionClassName => $errors) {
253
            foreach ($errors as $error) {
254
                $driverException = new class (...$error)
0 ignored issues
show
Bug introduced by
$error is expanded, but the parameter $code of anonymous//tests/Doctrin...st.php$1::__construct() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

254
                $driverException = new class (/** @scrutinizer ignore-type */ ...$error)
Loading history...
255
                    extends Exception
256
                    implements DriverExceptionInterface
257
                {
258
                    /** @var string|null */
259
                    private $sqlState;
260
261
                    public function __construct(int $code, ?string $sqlState = null, string $message = '')
262
                    {
263
                        parent::__construct($message, $code);
264
265
                        $this->sqlState = $sqlState;
266
                    }
267
268
                    /**
269
                     * {@inheritDoc}
270
                     */
271
                    public function getSQLState() : ?string
272
                    {
273
                        return $this->sqlState;
274
                    }
275
                };
276
277
                $data[] = [$driverException, $convertedExceptionClassName];
278
            }
279
        }
280
281
        return $data;
282
    }
283
}
284