From d284346d54260353efa09c96602c19d77821cb43 Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 01:10:45 -0600 Subject: [PATCH 01/11] Gets unit test working. Still needs work and testing expanded. Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- .../Container/TestAsset/SetupTrait.php | 2 +- test/unit/AdapterServiceFactoryTest.php | 113 -------- test/unit/AdapterTest.php | 200 +++---------- test/unit/ConfigProviderTest.php | 238 +++++++++++----- .../ConnectionInterfaceFactoryFactoryTest.php | 129 +++++++++ .../DriverInterfaceFactoryFactoryTest.php | 136 +++++++++ .../MetadataInterfaceFactoryTest.php | 40 +++ .../Container/PdoConnectionFactoryTest.php | 100 +++++++ test/unit/Container/PdoDriverFactoryTest.php | 20 ++ test/unit/Container/PdoResultFactoryTest.php | 25 ++ .../Container/PdoStatementFactoryTest.php | 60 ++++ .../PlatformInterfaceFactoryFactoryTest.php | 30 ++ .../PlatformInterfaceFactoryTest.php | 24 ++ .../Driver/DatabasePlatformNameTraitTest.php | 53 ++++ test/unit/Driver/Pdo/ConnectionTest.php | 39 +-- .../Driver/Pdo/ConnectionTransactionsTest.php | 161 ----------- .../Pdo/Feature/SqliteRowCounterTest.php | 25 ++ test/unit/Driver/Pdo/PdoTest.php | 13 +- test/unit/Driver/Pdo/ResultTest.php | 109 ------- test/unit/Driver/Pdo/StatementTest.php | 84 ------ test/unit/Platform/SqliteTest.php | 111 ++++---- test/unit/Platform/_files/.gitignore | 2 - .../Platform/Ddl/AlterTableDecoratorTest.php | 252 ++++++++++++++++ .../Platform/Ddl/CreateTableDecoratorTest.php | 226 +++++++++++++++ .../unit/Sql/Platform/SelectDecoratorTest.php | 269 ++++++++---------- test/unit/Sql/Platform/SqliteTest.php | 61 +++- test/unit/TestAsset/ConnectionWrapper.php | 23 -- test/unit/TestAsset/PdoStubDriver.php | 31 -- test/unit/TestAsset/TemporaryResultSet.php | 9 - 29 files changed, 1557 insertions(+), 1028 deletions(-) delete mode 100644 test/unit/AdapterServiceFactoryTest.php create mode 100644 test/unit/Container/ConnectionInterfaceFactoryFactoryTest.php create mode 100644 test/unit/Container/DriverInterfaceFactoryFactoryTest.php create mode 100644 test/unit/Container/MetadataInterfaceFactoryTest.php create mode 100644 test/unit/Container/PdoConnectionFactoryTest.php create mode 100644 test/unit/Container/PdoDriverFactoryTest.php create mode 100644 test/unit/Container/PdoResultFactoryTest.php create mode 100644 test/unit/Container/PdoStatementFactoryTest.php create mode 100644 test/unit/Container/PlatformInterfaceFactoryFactoryTest.php create mode 100644 test/unit/Container/PlatformInterfaceFactoryTest.php create mode 100644 test/unit/Driver/DatabasePlatformNameTraitTest.php delete mode 100644 test/unit/Driver/Pdo/ConnectionTransactionsTest.php create mode 100644 test/unit/Driver/Pdo/Feature/SqliteRowCounterTest.php delete mode 100644 test/unit/Driver/Pdo/ResultTest.php delete mode 100644 test/unit/Driver/Pdo/StatementTest.php delete mode 100644 test/unit/Platform/_files/.gitignore create mode 100644 test/unit/Sql/Platform/Ddl/AlterTableDecoratorTest.php create mode 100644 test/unit/Sql/Platform/Ddl/CreateTableDecoratorTest.php delete mode 100644 test/unit/TestAsset/ConnectionWrapper.php delete mode 100644 test/unit/TestAsset/PdoStubDriver.php delete mode 100644 test/unit/TestAsset/TemporaryResultSet.php diff --git a/test/integration/Container/TestAsset/SetupTrait.php b/test/integration/Container/TestAsset/SetupTrait.php index 7c02a3b..dfcd9c2 100644 --- a/test/integration/Container/TestAsset/SetupTrait.php +++ b/test/integration/Container/TestAsset/SetupTrait.php @@ -11,8 +11,8 @@ use PhpDb\Adapter\Driver\DriverInterface; use PhpDb\Adapter\Sqlite\ConfigProvider; use PhpDb\Adapter\Sqlite\Driver\Pdo\Pdo; +use PhpDb\ConfigProvider as LaminasDbConfigProvider; use PhpDb\Container\AdapterManager; -use PhpDb\Container\ConfigProvider as LaminasDbConfigProvider; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Psr\Container\ContainerInterface; diff --git a/test/unit/AdapterServiceFactoryTest.php b/test/unit/AdapterServiceFactoryTest.php deleted file mode 100644 index 6a931f9..0000000 --- a/test/unit/AdapterServiceFactoryTest.php +++ /dev/null @@ -1,113 +0,0 @@ -getDependencies(); - if (array_key_exists('services', $config) && is_array($config['services'])) { - $config['services']['config'] = $dbConfig; - } - - return new ServiceManager($config); - } - - #[Override] - protected function setUp(): void - { - $this->factory = new AdapterServiceFactory(); - } - - /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function testV3FactoryReturnsDefaultAdapter(): void - { - $this->expectNotToPerformAssertions(); - - $services = $this->createServiceManager([ - 'db' => [ - 'driver' => 'Pdo_Sqlite', - 'database' => ':memory:', - ], - ]); - - $this->factory->__invoke($services, Adapter::class); - } - - /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function testV3FactoryReturnsDefaultAdapterWithDefaultProfiler(): void - { - $services = $this->createServiceManager([ - 'db' => [ - 'driver' => 'Pdo_Sqlite', - 'database' => ':memory:', - 'profiler' => true, - ], - ]); - - $adapter = $this->factory->__invoke($services, Adapter::class); - self::assertInstanceOf(ProfilerInterface::class, $adapter->getProfiler()); - } - - /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function testV3FactoryReturnsDefaultAdapterWithProfilerClassname(): void - { - $services = $this->createServiceManager([ - 'db' => [ - 'driver' => 'Pdo_Sqlite', - 'database' => ':memory:', - 'profiler' => Profiler::class, - ], - ]); - - $adapter = $this->factory->__invoke($services, Adapter::class); - self::assertInstanceOf(ProfilerInterface::class, $adapter->getProfiler()); - } - - /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function testV3FactoryReturnsDefaultAdapterWithProfilerInstance(): void - { - $services = $this->createServiceManager([ - 'db' => [ - 'driver' => 'Pdo_Sqlite', - 'database' => ':memory:', - 'profiler' => $this->getMockBuilder(ProfilerInterface::class)->getMock(), - ], - ]); - - $adapter = $this->factory->__invoke($services, Adapter::class); - self::assertInstanceOf(ProfilerInterface::class, $adapter->getProfiler()); - } -} diff --git a/test/unit/AdapterTest.php b/test/unit/AdapterTest.php index 749fef1..7f96cb0 100644 --- a/test/unit/AdapterTest.php +++ b/test/unit/AdapterTest.php @@ -1,33 +1,27 @@ adapter->setProfiler(new Profiler\Profiler()); - self::assertSame($this->adapter, $ret); - } + protected Adapter $adapter; - #[TestDox('unit test: Test getProfiler() will store profiler')] - public function testGetProfiler(): void + /** + * @throws \Exception + */ + #[Override] + protected function setUp(): void { - $this->adapter->setProfiler($profiler = new Profiler\Profiler()); - self::assertSame($profiler, $this->adapter->getProfiler()); + $this->mockConnection = $this->createMock(AbstractPdoConnection::class); + $this->mockPlatform = new SqlitePlatform($this->createMock(PdoDriverInterface::class)); + $this->mockStatement = $this->getMockBuilder(Statement::class)->getMock(); + $this->mockResultSet = $this->getMockBuilder(ResultSetInterface::class)->getMock(); + $resultInterface = $this->getMockBuilder(ResultInterface::class)->getMock(); + $this->mockDriver = $this->getMockBuilder(Pdo::class) + ->setConstructorArgs([ + $this->mockConnection, + $this->mockStatement, + $resultInterface, + ]) + ->getMock(); - $adapter = new Adapter(['driver' => $this->mockDriver, 'profiler' => true], $this->mockPlatform); - self::assertInstanceOf(Profiler\Profiler::class, $adapter->getProfiler()); - } + $this->mockDriver->method('getDatabasePlatformName')->willReturn('Sqlite'); + $this->mockDriver->method('checkEnvironment')->willReturn(true); + $this->mockDriver->method('getConnection')->willReturn($this->mockConnection); + $this->mockDriver->method('createStatement')->willReturn($this->mockStatement); - #[TestDox('unit test: Test createDriverFromParameters() will create proper driver type')] - public function testCreateDriver(): void - { - if (extension_loaded('pdo')) { - $adapter = new Adapter(['driver' => 'pdo_sqlite'], $this->mockPlatform); - self::assertInstanceOf(Pdo::class, $adapter->driver); - unset($adapter); - } + $this->adapter = new Adapter( + $this->mockDriver, + $this->mockPlatform, + $this->mockResultSet + ); } - #[TestDox('unit test: Test createPlatformFromDriver() will create proper platform from driver')] - public function testCreatePlatform(): void + #[TestDox('unit test: Test setProfiler() will store profiler')] + public function testSetProfiler(): void { - $driver = clone $this->mockDriver; - $driver->expects($this->any())->method('getDatabasePlatformName')->willReturn('Sqlite'); - $adapter = new Adapter($driver); - self::assertInstanceOf(SqlitePlatform::class, $adapter->platform); - unset($adapter, $driver); + $ret = $this->adapter->setProfiler(new Profiler\Profiler()); + self::assertSame($this->adapter, $ret); } #[TestDox('unit test: Test getDriver() will return driver object')] @@ -100,12 +97,6 @@ public function testGetPlatform(): void self::assertSame($this->mockPlatform, $this->adapter->getPlatform()); } - #[TestDox('unit test: Test getPlatform() returns platform object')] - public function testGetQueryResultSetPrototype(): void - { - self::assertInstanceOf(ResultSetInterface::class, $this->adapter->getQueryResultSetPrototype()); - } - #[TestDox('unit test: Test getCurrentSchema() returns current schema from connection object')] public function testGetCurrentSchema(): void { @@ -123,29 +114,6 @@ public function testQueryWhenPreparedProducesStatement(): void self::assertSame($this->mockStatement, $s); } - /** - * @throws Exception - * @throws \Exception - */ - #[Group('#210')] - public function testProducedResultSetPrototypeIsDifferentForEachQuery(): void - { - $statement = $this->createMock(StatementInterface::class); - $result = $this->createMock(ResultInterface::class); - - $this->mockDriver->method('createStatement') - ->willReturn($statement); - $this->mockStatement->method('execute') - ->willReturn($result); - $result->method('isQueryResult') - ->willReturn(true); - - self::assertNotSame( - $this->adapter->query('SELECT foo', []), - $this->adapter->query('SELECT foo', []) - ); - } - /** * @throws \Exception */ @@ -164,101 +132,9 @@ public function testQueryWhenPreparedWithParameterArrayProducesResult(): void self::assertSame($result, $r); } - /** - * @throws \Exception - */ - #[TestDox('unit test: Test query() in prepare mode, with ParameterContainer, produces a result object')] - public function testQueryWhenPreparedWithParameterContainerProducesResult(): void - { - $sql = 'SELECT foo'; - $parameterContainer = $this->getMockBuilder(ParameterContainer::class)->getMock(); - $result = $this->getMockBuilder(ResultInterface::class)->getMock(); - $this->mockDriver->expects($this->any())->method('createStatement') - ->with($sql)->willReturn($this->mockStatement); - $this->mockStatement->expects($this->any())->method('execute')->willReturn($result); - $result->expects($this->any())->method('isQueryResult')->willReturn(true); - - $r = $this->adapter->query($sql, $parameterContainer); - self::assertInstanceOf(ResultSet::class, $r); - } - - /** - * @throws \Exception - */ - #[TestDox('unit test: Test query() in execute mode produces a driver result object')] - public function testQueryWhenExecutedProducesAResult(): void - { - $sql = 'SELECT foo'; - $result = $this->getMockBuilder(ResultInterface::class)->getMock(); - $this->mockConnection->expects($this->any())->method('execute')->with($sql)->willReturn($result); - - $r = $this->adapter->query($sql, AdapterInterface::QUERY_MODE_EXECUTE); - self::assertSame($result, $r); - } - - /** - * @throws \Exception - */ - #[TestDox('unit test: Test query() in execute mode produces a resultset object')] - public function testQueryWhenExecutedProducesAResultSetObjectWhenResultIsQuery(): void - { - $sql = 'SELECT foo'; - - $result = $this->getMockBuilder(ResultInterface::class)->getMock(); - $this->mockConnection->expects($this->any())->method('execute')->with($sql)->willReturn($result); - $result->expects($this->any())->method('isQueryResult')->willReturn(true); - - $r = $this->adapter->query($sql, AdapterInterface::QUERY_MODE_EXECUTE); - self::assertInstanceOf(ResultSet::class, $r); - - $r = $this->adapter->query($sql, AdapterInterface::QUERY_MODE_EXECUTE, new TemporaryResultSet()); - self::assertInstanceOf(TemporaryResultSet::class, $r); - } - #[TestDox('unit test: Test createStatement() produces a statement object')] public function testCreateStatement(): void { self::assertSame($this->mockStatement, $this->adapter->createStatement()); } - - public function testMagicGet(): void - { - // @codingStandardsIgnoreEnd - self::assertSame($this->mockDriver, $this->adapter->driver); - /** @psalm-suppress UndefinedMagicPropertyFetch */ - self::assertSame($this->mockDriver, $this->adapter->DrivER); - /** @psalm-suppress UndefinedMagicPropertyFetch */ - self::assertSame($this->mockPlatform, $this->adapter->PlatForm); - self::assertSame($this->mockPlatform, $this->adapter->platform); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid magic'); - $this->adapter->foo; - } - - // @codingStandardsIgnoreStart - - /** - * @throws Exception - */ - #[Override] - protected function setUp(): void - { - $this->mockConnection = $this->createMock(ConnectionInterface::class); - $this->mockPlatform = new SqlitePlatform($this->createMock(PdoDriverInterface::class)); - $this->mockStatement = $this->getMockBuilder(Statement::class)->getMock(); - $this->mockDriver = $this->getMockBuilder(Pdo::class) - ->setConstructorArgs([ - $this->mockConnection, - $this->mockStatement, - ]) - ->getMock(); - - $this->mockDriver->method('getDatabasePlatformName')->willReturn('Sqlite'); - $this->mockDriver->method('checkEnvironment')->willReturn(true); - $this->mockDriver->method('getConnection')->willReturn($this->mockConnection); - $this->mockDriver->method('createStatement')->willReturn($this->mockStatement); - - $this->adapter = new Adapter($this->mockDriver, $this->mockPlatform); - } } diff --git a/test/unit/ConfigProviderTest.php b/test/unit/ConfigProviderTest.php index 9f1fffa..0af2103 100644 --- a/test/unit/ConfigProviderTest.php +++ b/test/unit/ConfigProviderTest.php @@ -19,93 +19,195 @@ use PhpDb\Adapter\Profiler\ProfilerInterface; use PhpDb\Adapter\Sqlite\ConfigProvider; use PhpDb\Adapter\Sqlite\Container; -use PhpDb\Adapter\Sqlite\Driver; -use PhpDb\Adapter\Sqlite\Metadata; -use PhpDb\Adapter\Sqlite\Platform; +use PhpDb\Adapter\Sqlite\Driver\Pdo\Connection; +use PhpDb\Adapter\Sqlite\Driver\Pdo\Pdo; +use PhpDb\Adapter\Sqlite\Metadata\Source\SqliteMetadata; +use PhpDb\Adapter\Sqlite\Platform\Sqlite; +use PhpDb\Container\AdapterAbstractServiceFactory; use PhpDb\Container\AdapterManager; +use PhpDb\Container\ConnectionInterfaceFactoryFactoryInterface; +use PhpDb\Container\DriverInterfaceFactoryFactoryInterface; +use PhpDb\Container\PlatformInterfaceFactoryFactoryInterface; use PhpDb\Metadata\MetadataInterface; use PhpDb\ResultSet; -use PHPUnit\Framework\Attributes\CoversMethod; -use PHPUnit\Framework\Attributes\Depends; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -#[CoversMethod(ConfigProvider::class, '__invoke')] -#[CoversMethod(ConfigProvider::class, 'getDependencies')] -#[CoversMethod(ConfigProvider::class, 'getAdapterManagerConfig')] +#[CoversClass(ConfigProvider::class)] final class ConfigProviderTest extends TestCase { - /** @var array>> */ - private array $config = [ - 'aliases' => [ - MetadataInterface::class => Metadata\Source\SqliteMetadata::class, - ], - 'factories' => [ - Metadata\Source\SqliteMetadata::class => Container\MetadataInterfaceFactory::class, - ], - 'delegators' => [ - AdapterManager::class => [ - Container\AdapterManagerDelegator::class, - ], - ], - ]; - - private array $adapterManagerConfig = [ - 'aliases' => [ - 'SQLite' => Driver\Pdo\Pdo::class, - 'Sqlite' => Driver\Pdo\Pdo::class, - 'sqlite' => Driver\Pdo\Pdo::class, - 'pdo' => Driver\Pdo\Pdo::class, - 'pdo_sqlite' => Driver\Pdo\Pdo::class, - 'pdosqlite' => Driver\Pdo\Pdo::class, - 'pdodriver' => Driver\Pdo\Pdo::class, - ConnectionInterface::class => Driver\Pdo\Connection::class, - PdoConnectionInterface::class => Driver\Pdo\Connection::class, - DriverInterface::class => Driver\Pdo\Pdo::class, - PdoDriverInterface::class => Driver\Pdo\Pdo::class, - PlatformInterface::class => Platform\Sqlite::class, + private ConfigProvider $configProvider; + + protected function setUp(): void + { + $this->configProvider = new ConfigProvider(); + } + + public function testInvokeReturnsExpectedStructure(): void + { + $config = ($this->configProvider)(); + + self::assertIsArray($config); + self::assertArrayHasKey('dependencies', $config); + self::assertArrayHasKey(AdapterManager::class, $config); + } + + public function testGetDependenciesReturnsCorrectStructure(): void + { + $dependencies = $this->configProvider->getDependencies(); + + self::assertIsArray($dependencies); + self::assertArrayHasKey('abstract_factories', $dependencies); + self::assertArrayHasKey('aliases', $dependencies); + self::assertArrayHasKey('factories', $dependencies); + self::assertArrayHasKey('delegators', $dependencies); + } + + public function testGetDependenciesContainsAbstractFactories(): void + { + $dependencies = $this->configProvider->getDependencies(); + + self::assertContains( + AdapterAbstractServiceFactory::class, + $dependencies['abstract_factories'] + ); + } + + public function testGetDependenciesContainsMetadataAlias(): void + { + $dependencies = $this->configProvider->getDependencies(); + + self::assertArrayHasKey(MetadataInterface::class, $dependencies['aliases']); + self::assertSame( + SqliteMetadata::class, + $dependencies['aliases'][MetadataInterface::class] + ); + } + + public function testGetDependenciesContainsMetadataFactory(): void + { + $dependencies = $this->configProvider->getDependencies(); + + self::assertArrayHasKey(SqliteMetadata::class, $dependencies['factories']); + self::assertSame( + Container\MetadataInterfaceFactory::class, + $dependencies['factories'][SqliteMetadata::class] + ); + } + + public function testGetDependenciesContainsDelegators(): void + { + $dependencies = $this->configProvider->getDependencies(); + + self::assertArrayHasKey(AdapterManager::class, $dependencies['delegators']); + self::assertContains( + Container\AdapterManagerDelegator::class, + $dependencies['delegators'][AdapterManager::class] + ); + } + + public function testGetAdapterManagerConfigReturnsCorrectStructure(): void + { + $config = $this->configProvider->getAdapterManagerConfig(); + + self::assertIsArray($config); + self::assertArrayHasKey('aliases', $config); + self::assertArrayHasKey('factories', $config); + self::assertArrayHasKey('invokables', $config); + } + + public function testGetAdapterManagerConfigContainsDriverAliases(): void + { + $config = $this->configProvider->getAdapterManagerConfig(); + + $expectedAliases = [ + 'SQLite' => Pdo::class, + 'Sqlite' => Pdo::class, + 'sqlite' => Pdo::class, + 'pdo' => Pdo::class, + 'pdo_sqlite' => Pdo::class, + 'pdosqlite' => Pdo::class, + 'pdodriver' => Pdo::class, + ]; + + foreach ($expectedAliases as $alias => $target) { + self::assertArrayHasKey($alias, $config['aliases']); + self::assertSame($target, $config['aliases'][$alias]); + } + } + + public function testGetAdapterManagerConfigContainsInterfaceAliases(): void + { + $config = $this->configProvider->getAdapterManagerConfig(); + + $expectedAliases = [ + ConnectionInterface::class => Connection::class, + PdoConnectionInterface::class => Connection::class, + DriverInterface::class => Pdo::class, + PdoDriverInterface::class => Pdo::class, + PlatformInterface::class => Sqlite::class, ProfilerInterface::class => Profiler::class, ResultInterface::class => Result::class, ResultSet\ResultSetInterface::class => ResultSet\ResultSet::class, StatementInterface::class => Statement::class, - ], - 'factories' => [ - AdapterInterface::class => Container\AdapterFactory::class, - Driver\Pdo\Connection::class => Container\PdoConnectionFactory::class, - Driver\Pdo\Pdo::class => Container\PdoDriverFactory::class, - Result::class => Container\PdoResultFactory::class, - Statement::class => Container\PdoStatementFactory::class, - Platform\Sqlite::class => Container\PlatformInterfaceFactory::class, - //Profiler::class => InvokableFactory::class, - ResultSet\ResultSet::class => InvokableFactory::class, - ], - ]; + ]; - public function testProvidesExpectedDependencies(): ConfigProvider + foreach ($expectedAliases as $interface => $implementation) { + self::assertArrayHasKey($interface, $config['aliases']); + self::assertSame($implementation, $config['aliases'][$interface]); + } + } + + public function testGetAdapterManagerConfigContainsFactoryFactoryAliases(): void { - $provider = new ConfigProvider(); - self::assertEquals($this->config, $provider->getDependencies()); + $config = $this->configProvider->getAdapterManagerConfig(); + + $expectedAliases = [ + ConnectionInterfaceFactoryFactoryInterface::class => Container\ConnectionInterfaceFactoryFactory::class, + DriverInterfaceFactoryFactoryInterface::class => Container\DriverInterfaceFactoryFactory::class, + PlatformInterfaceFactoryFactoryInterface::class => Container\PlatformInterfaceFactoryFactory::class, + ]; - return $provider; + foreach ($expectedAliases as $interface => $implementation) { + self::assertArrayHasKey($interface, $config['aliases']); + self::assertSame($implementation, $config['aliases'][$interface]); + } } - public function testProvidesExpectedAdapterManagerConfiguration(): void + public function testGetAdapterManagerConfigContainsFactories(): void { - $provider = new ConfigProvider(); - self::assertEquals( - $this->adapterManagerConfig, - $provider->getAdapterManagerConfig() - ); + $config = $this->configProvider->getAdapterManagerConfig(); + + $expectedFactories = [ + AdapterInterface::class => Container\AdapterFactory::class, + Connection::class => Container\PdoConnectionFactory::class, + Pdo::class => Container\PdoDriverFactory::class, + Result::class => Container\PdoResultFactory::class, + Statement::class => Container\PdoStatementFactory::class, + Sqlite::class => Container\PlatformInterfaceFactory::class, + Profiler::class => InvokableFactory::class, + ResultSet\ResultSet::class => InvokableFactory::class, + ]; + + foreach ($expectedFactories as $service => $factory) { + self::assertArrayHasKey($service, $config['factories']); + self::assertSame($factory, $config['factories'][$service]); + } } - #[Depends('testProvidesExpectedDependencies')] - public function testInvocationProvidesDependencyConfiguration(ConfigProvider $provider): void + public function testGetAdapterManagerConfigContainsInvokables(): void { - self::assertEquals( - [ - 'dependencies' => $provider->getDependencies(), - AdapterManager::class => $provider->getAdapterManagerConfig(), - ], - $provider() - ); + $config = $this->configProvider->getAdapterManagerConfig(); + + $expectedInvokables = [ + Container\ConnectionInterfaceFactoryFactory::class, + Container\DriverInterfaceFactoryFactory::class, + Container\PlatformInterfaceFactoryFactory::class, + ]; + + foreach ($expectedInvokables as $invokable) { + self::assertArrayHasKey($invokable, $config['invokables']); + self::assertSame($invokable, $config['invokables'][$invokable]); + } } } diff --git a/test/unit/Container/ConnectionInterfaceFactoryFactoryTest.php b/test/unit/Container/ConnectionInterfaceFactoryFactoryTest.php new file mode 100644 index 0000000..d6cd4d6 --- /dev/null +++ b/test/unit/Container/ConnectionInterfaceFactoryFactoryTest.php @@ -0,0 +1,129 @@ +createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [ + 'driver' => 'sqlite', + ], + ], + ], + AdapterManager::class => [ + 'aliases' => [ + 'sqlite' => Pdo::class, + ], + ], + ], + ], + ]); + + $factoryFactory = new ConnectionInterfaceFactoryFactory(); + $result = $factoryFactory($containerMock, 'test_adapter'); + + self::assertIsCallable($result); + } + + public function testInvokeReturnsPdoConnectionFactory(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [ + 'driver' => 'sqlite', + ], + ], + ], + AdapterManager::class => [ + 'aliases' => [ + 'sqlite' => Pdo::class, + ], + ], + ], + ], + ]); + + $factoryFactory = new ConnectionInterfaceFactoryFactory(); + $result = $factoryFactory($containerMock, 'test_adapter'); + + self::assertInstanceOf(PdoConnectionFactory::class, $result); + } + + public function testInvokeThrowsExceptionWhenDriverNotConfigured(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [], + ], + ], + ], + ], + ]); + + $factoryFactory = new ConnectionInterfaceFactoryFactory(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Named adapter "test_adapter" is not configured with a driver'); + + $factoryFactory($containerMock, 'test_adapter'); + } + + public function testInvokeThrowsExceptionForUnknownDriver(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [ + 'driver' => 'unknown', + ], + ], + ], + AdapterManager::class => [ + 'aliases' => [], + ], + ], + ], + ]); + + $factoryFactory = new ConnectionInterfaceFactoryFactory(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('No connection factory found for driver "unknown"'); + + $factoryFactory($containerMock, 'test_adapter'); + } +} diff --git a/test/unit/Container/DriverInterfaceFactoryFactoryTest.php b/test/unit/Container/DriverInterfaceFactoryFactoryTest.php new file mode 100644 index 0000000..efbfe5e --- /dev/null +++ b/test/unit/Container/DriverInterfaceFactoryFactoryTest.php @@ -0,0 +1,136 @@ +createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [ + 'driver' => 'sqlite', + ], + ], + ], + AdapterManager::class => [ + 'aliases' => [ + 'sqlite' => Pdo::class, + ], + 'factories' => [ + Pdo::class => PdoDriverFactory::class, + ], + ], + ], + ], + ]); + + $factoryFactory = new DriverInterfaceFactoryFactory(); + $result = $factoryFactory($containerMock, 'test_adapter'); + + self::assertIsCallable($result); + } + + public function testInvokeReturnsPdoDriverFactory(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [ + 'driver' => 'sqlite', + ], + ], + ], + AdapterManager::class => [ + 'aliases' => [ + 'sqlite' => Pdo::class, + ], + 'factories' => [ + Pdo::class => PdoDriverFactory::class, + ], + ], + ], + ], + ]); + + $factoryFactory = new DriverInterfaceFactoryFactory(); + $result = $factoryFactory($containerMock, 'test_adapter'); + + self::assertInstanceOf(PdoDriverFactory::class, $result); + } + + public function testInvokeThrowsExceptionWhenDriverNotConfigured(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [], + ], + ], + ], + ], + ]); + + $factoryFactory = new DriverInterfaceFactoryFactory(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Named adapter "test_adapter" is not configured with a driver'); + + $factoryFactory($containerMock, 'test_adapter'); + } + + public function testInvokeWithDriverNotInAliases(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get')->willReturnMap([ + [ + 'config', + [ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [ + 'driver' => Pdo::class, + ], + ], + ], + AdapterManager::class => [ + 'aliases' => [], + 'factories' => [ + Pdo::class => PdoDriverFactory::class, + ], + ], + ], + ], + ]); + + $factoryFactory = new DriverInterfaceFactoryFactory(); + $result = $factoryFactory($containerMock, 'test_adapter'); + + self::assertInstanceOf(PdoDriverFactory::class, $result); + } +} diff --git a/test/unit/Container/MetadataInterfaceFactoryTest.php b/test/unit/Container/MetadataInterfaceFactoryTest.php new file mode 100644 index 0000000..525b84f --- /dev/null +++ b/test/unit/Container/MetadataInterfaceFactoryTest.php @@ -0,0 +1,40 @@ +createMock(PdoDriverInterface::class); + $platformMock = $this->createMock(PlatformInterface::class); + $platformMock->method('getName')->willReturn('SQLite'); + $resultSetMock = $this->createMock(ResultSetInterface::class); + + $adapterMock = new Adapter($driverMock, $platformMock, $resultSetMock); + + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get') + ->with(AdapterInterface::class) + ->willReturn($adapterMock); + + $factory = new MetadataInterfaceFactory(); + $metadata = $factory($containerMock); + + self::assertInstanceOf(SqliteMetadata::class, $metadata); + } +} diff --git a/test/unit/Container/PdoConnectionFactoryTest.php b/test/unit/Container/PdoConnectionFactoryTest.php new file mode 100644 index 0000000..3a5aee7 --- /dev/null +++ b/test/unit/Container/PdoConnectionFactoryTest.php @@ -0,0 +1,100 @@ +createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([ + 'db' => [ + 'connection' => [ + 'dsn' => 'sqlite::memory:', + ], + ], + ]); + + $factory = new PdoConnectionFactory(); + $connection = $factory($containerMock); + + self::assertInstanceOf(Connection::class, $connection); + } + + public function testInvokeWithoutConnectionConfig(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([ + 'db' => [], + ]); + + $factory = new PdoConnectionFactory(); + $connection = $factory($containerMock); + + self::assertInstanceOf(Connection::class, $connection); + } + + public function testInvokeWithoutDbConfig(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([]); + + $factory = new PdoConnectionFactory(); + $connection = $factory($containerMock); + + self::assertInstanceOf(Connection::class, $connection); + } + + public function testCreateFromConfigReturnsConnection(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([ + 'db' => [ + 'adapters' => [ + 'test_adapter' => [ + 'connection' => [ + 'dsn' => 'sqlite::memory:', + ], + ], + ], + ], + ]); + + $connection = PdoConnectionFactory::createFromConfig($containerMock, 'test_adapter'); + + self::assertInstanceOf(Connection::class, $connection); + } + + public function testCreateFromConfigWithoutAdapterConfig(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([ + 'db' => [ + 'adapters' => [], + ], + ]); + + $connection = PdoConnectionFactory::createFromConfig($containerMock, 'unknown_adapter'); + + self::assertInstanceOf(Connection::class, $connection); + } +} diff --git a/test/unit/Container/PdoDriverFactoryTest.php b/test/unit/Container/PdoDriverFactoryTest.php new file mode 100644 index 0000000..f8e2826 --- /dev/null +++ b/test/unit/Container/PdoDriverFactoryTest.php @@ -0,0 +1,20 @@ +createMock(ContainerInterface::class); + + $factory = new PdoResultFactory(); + $result = $factory($containerMock); + + self::assertInstanceOf(Result::class, $result); + } +} diff --git a/test/unit/Container/PdoStatementFactoryTest.php b/test/unit/Container/PdoStatementFactoryTest.php new file mode 100644 index 0000000..4cf5309 --- /dev/null +++ b/test/unit/Container/PdoStatementFactoryTest.php @@ -0,0 +1,60 @@ +createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([ + 'db' => [ + 'options' => [], + ], + ]); + + $factory = new PdoStatementFactory(); + $statement = $factory($containerMock); + + self::assertInstanceOf(Statement::class, $statement); + } + + public function testInvokeWithoutOptionsConfig(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([ + 'db' => [], + ]); + + $factory = new PdoStatementFactory(); + $statement = $factory($containerMock); + + self::assertInstanceOf(Statement::class, $statement); + } + + public function testInvokeWithoutDbConfig(): void + { + $containerMock = $this->createMock(ContainerInterface::class); + $containerMock->method('get') + ->with('config') + ->willReturn([]); + + $factory = new PdoStatementFactory(); + $statement = $factory($containerMock); + + self::assertInstanceOf(Statement::class, $statement); + } +} diff --git a/test/unit/Container/PlatformInterfaceFactoryFactoryTest.php b/test/unit/Container/PlatformInterfaceFactoryFactoryTest.php new file mode 100644 index 0000000..ec2c0b6 --- /dev/null +++ b/test/unit/Container/PlatformInterfaceFactoryFactoryTest.php @@ -0,0 +1,30 @@ +createMock(PdoDriverInterface::class); + + $platform = PlatformInterfaceFactory::fromDriver($driverMock); + + self::assertInstanceOf(Sqlite::class, $platform); + } +} diff --git a/test/unit/Driver/DatabasePlatformNameTraitTest.php b/test/unit/Driver/DatabasePlatformNameTraitTest.php new file mode 100644 index 0000000..e49d54e --- /dev/null +++ b/test/unit/Driver/DatabasePlatformNameTraitTest.php @@ -0,0 +1,53 @@ +traitObject = new class { + use DatabasePlatformNameTrait; + }; + } + + public function testGetDatabasePlatformNameWithCamelCaseFormat(): void + { + $result = $this->traitObject->getDatabasePlatformName(DriverInterface::NAME_FORMAT_CAMELCASE); + + self::assertSame('Sqlite', $result); + } + + public function testGetDatabasePlatformNameWithNaturalFormat(): void + { + $result = $this->traitObject->getDatabasePlatformName(DriverInterface::NAME_FORMAT_NATURAL); + + self::assertSame('SQLite', $result); + } + + public function testGetDatabasePlatformNameWithInvalidFormatThrowsException(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid name format provided'); + + $this->traitObject->getDatabasePlatformName('INVALID_FORMAT'); + } + + public function testGetDatabasePlatformNameDefaultsToCamelCase(): void + { + $result = $this->traitObject->getDatabasePlatformName(); + + self::assertSame('Sqlite', $result); + } +} diff --git a/test/unit/Driver/Pdo/ConnectionTest.php b/test/unit/Driver/Pdo/ConnectionTest.php index 3fd2866..53beed2 100644 --- a/test/unit/Driver/Pdo/ConnectionTest.php +++ b/test/unit/Driver/Pdo/ConnectionTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace PhpDbTest\Adapter\Sqlite\Sqlite\Driver\Pdo; +namespace PhpDbTest\Adapter\Sqlite\Driver\Pdo; use Exception; use Override; @@ -12,11 +12,15 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use function realpath; + #[CoversMethod(Connection::class, 'getResource')] #[CoversMethod(Connection::class, 'getDsn')] final class ConnectionTest extends TestCase { protected Connection $connection; + //protected string $dsn = 'sqlite::memory:'; + protected string $dsn = 'sqlite::memory:'; /** * Sets up the fixture, for example, opens a network connection. @@ -25,7 +29,9 @@ final class ConnectionTest extends TestCase #[Override] protected function setUp(): void { - $this->connection = new Connection(); + $this->connection = new Connection([ + 'dsn' => $this->dsn, + ]); } /** @@ -33,7 +39,7 @@ protected function setUp(): void */ public function testResource(): void { - $this->expectException(InvalidConnectionParametersException::class); + $this->expectNotToPerformAssertions(); $this->connection->getResource(); } @@ -42,23 +48,21 @@ public function testResource(): void */ public function testGetDsn(): void { - $dsn = "sqlite::memory:"; - $this->connection->setConnectionParameters(['dsn' => $dsn]); + $this->connection->setConnectionParameters(['dsn' => $this->dsn]); try { $this->connection->connect(); } catch (Exception) { } $responseString = $this->connection->getDsn(); - self::assertEquals($dsn, $responseString); + self::assertEquals($this->dsn, $responseString); } #[Group('2622')] public function testArrayOfConnectionParametersCreatesCorrectDsn(): void { $this->connection->setConnectionParameters([ - 'driver' => 'Pdo_Sqlite', - 'database' => ':memory', + 'dsn' => 'sqlite::memory:', ]); try { $this->connection->connect(); @@ -69,23 +73,4 @@ public function testArrayOfConnectionParametersCreatesCorrectDsn(): void self::assertStringStartsWith('sqlite:', $responseString); self::assertStringContainsString('memory', $responseString); } - - public function testDblibArrayOfConnectionParametersCreatesCorrectDsn(): void - { - $this->connection->setConnectionParameters([ - 'driver' => 'pdo_dblib', - 'charset' => 'UTF-8', - 'dbname' => 'foo', - 'port' => '1433', - 'version' => '7.3', - ]); - try { - $this->connection->connect(); - } catch (Exception) { - } - $responseString = $this->connection->getDsn(); - - $this->assertStringStartsWith('dblib:', $responseString); - $this->assertStringContainsString('foo', $responseString); - } } diff --git a/test/unit/Driver/Pdo/ConnectionTransactionsTest.php b/test/unit/Driver/Pdo/ConnectionTransactionsTest.php deleted file mode 100644 index 9980060..0000000 --- a/test/unit/Driver/Pdo/ConnectionTransactionsTest.php +++ /dev/null @@ -1,161 +0,0 @@ -wrapper = new ConnectionWrapper(); - } - - public function testBeginTransactionReturnsInstanceOfConnection(): void - { - self::assertInstanceOf(Connection::class, $this->wrapper->beginTransaction()); - } - - public function testBeginTransactionSetsInTransactionAtTrue(): void - { - $this->wrapper->beginTransaction(); - self::assertTrue($this->wrapper->inTransaction()); - } - - public function testCommitReturnsInstanceOfConnection(): void - { - $this->wrapper->beginTransaction(); - self::assertInstanceOf(Connection::class, $this->wrapper->commit()); - } - - public function testCommitSetsInTransactionAtFalse(): void - { - $this->wrapper->beginTransaction(); - $this->wrapper->commit(); - self::assertFalse($this->wrapper->inTransaction()); - } - - /** - * Standalone commit after a SET autocommit=0; - */ - public function testCommitWithoutBeginReturnsInstanceOfConnection(): void - { - self::assertInstanceOf(Connection::class, $this->wrapper->commit()); - } - - public function testNestedTransactionsCommit(): void - { - $nested = 0; - - self::assertFalse($this->wrapper->inTransaction()); - - // 1st transaction - $this->wrapper->beginTransaction(); - self::assertTrue($this->wrapper->inTransaction()); - self::assertSame(++$nested, $this->wrapper->getNestedTransactionsCount()); - - // 2nd transaction - $this->wrapper->beginTransaction(); - self::assertTrue($this->wrapper->inTransaction()); - self::assertSame(++$nested, $this->wrapper->getNestedTransactionsCount()); - - // 1st commit - $this->wrapper->commit(); - self::assertTrue($this->wrapper->inTransaction()); - self::assertSame(--$nested, $this->wrapper->getNestedTransactionsCount()); - - // 2nd commit - $this->wrapper->commit(); - self::assertFalse($this->wrapper->inTransaction()); - self::assertSame(--$nested, $this->wrapper->getNestedTransactionsCount()); - } - - public function testNestedTransactionsRollback(): void - { - $nested = 0; - - self::assertFalse($this->wrapper->inTransaction()); - - // 1st transaction - $this->wrapper->beginTransaction(); - self::assertTrue($this->wrapper->inTransaction()); - self::assertSame(++$nested, $this->wrapper->getNestedTransactionsCount()); - - // 2nd transaction - $this->wrapper->beginTransaction(); - self::assertTrue($this->wrapper->inTransaction()); - self::assertSame(++$nested, $this->wrapper->getNestedTransactionsCount()); - - // Rollback - $this->wrapper->rollback(); - self::assertFalse($this->wrapper->inTransaction()); - self::assertSame(0, $this->wrapper->getNestedTransactionsCount()); - } - - public function testRollbackDisconnectedThrowsException(): void - { - $this->wrapper->disconnect(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Must be connected before you can rollback'); - $this->wrapper->rollback(); - } - - public function testRollbackReturnsInstanceOfConnection(): void - { - $this->wrapper->beginTransaction(); - self::assertInstanceOf(Connection::class, $this->wrapper->rollback()); - } - - public function testRollbackSetsInTransactionAtFalse(): void - { - $this->wrapper->beginTransaction(); - $this->wrapper->rollback(); - self::assertFalse($this->wrapper->inTransaction()); - } - - public function testRollbackWithoutBeginThrowsException(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Must call beginTransaction() before you can rollback'); - $this->wrapper->rollback(); - } - - /** - * Standalone commit after a SET autocommit=0; - */ - public function testStandaloneCommit(): void - { - self::assertFalse($this->wrapper->inTransaction()); - self::assertSame(0, $this->wrapper->getNestedTransactionsCount()); - - $this->wrapper->commit(); - - self::assertFalse($this->wrapper->inTransaction()); - self::assertSame(0, $this->wrapper->getNestedTransactionsCount()); - } -} diff --git a/test/unit/Driver/Pdo/Feature/SqliteRowCounterTest.php b/test/unit/Driver/Pdo/Feature/SqliteRowCounterTest.php new file mode 100644 index 0000000..97bb156 --- /dev/null +++ b/test/unit/Driver/Pdo/Feature/SqliteRowCounterTest.php @@ -0,0 +1,25 @@ +rowCounter = new SqliteRowCounter(); + } + + public function testRowCounterExists(): void + { + self::assertInstanceOf(SqliteRowCounter::class, $this->rowCounter); + } +} diff --git a/test/unit/Driver/Pdo/PdoTest.php b/test/unit/Driver/Pdo/PdoTest.php index 97f7259..0237612 100644 --- a/test/unit/Driver/Pdo/PdoTest.php +++ b/test/unit/Driver/Pdo/PdoTest.php @@ -2,10 +2,9 @@ declare(strict_types=1); -namespace PhpDbTest\Adapter\Sqlite\Sqlite\Driver\Pdo; +namespace PhpDbTest\Adapter\Sqlite\Driver\Pdo; use Override; -use PhpDb\Adapter\Driver\Pdo\Result; use PhpDb\Adapter\Driver\PdoDriverAwareInterface; use PhpDb\Adapter\Driver\PdoDriverInterface; use PhpDb\Adapter\Driver\ResultInterface; @@ -18,7 +17,6 @@ use PHPUnit\Framework\TestCase; #[CoversMethod(Pdo::class, 'getDatabasePlatformName')] -#[CoversMethod(Pdo::class, 'getResultPrototype')] final class PdoTest extends TestCase { protected Pdo $pdo; @@ -30,7 +28,7 @@ final class PdoTest extends TestCase #[Override] protected function setUp(): void { - $connection = new Connection(); + $connection = new Connection(['dsn' => ':memory:']); /** @var StatementInterface&PdoDriverAwareInterface $statementPrototype */ $statementPrototype = $this->createMockForIntersectionOfInterfaces([ @@ -94,11 +92,4 @@ public function testFormatParameterNameWithInvalidCharacters(string $name): void $this->expectException(RuntimeException::class); $this->pdo->formatParameterName($name); } - - public function testGetResultPrototype(): void - { - $resultPrototype = $this->pdo->getResultPrototype(); - - self::assertInstanceOf(Result::class, $resultPrototype); - } } diff --git a/test/unit/Driver/Pdo/ResultTest.php b/test/unit/Driver/Pdo/ResultTest.php deleted file mode 100644 index bc0d1e6..0000000 --- a/test/unit/Driver/Pdo/ResultTest.php +++ /dev/null @@ -1,109 +0,0 @@ -getMockBuilder(PDOStatement::class)->getMock(); - $stub->expects($this->any()) - ->method('fetch') - ->willReturnCallback(fn() => uniqid()); - - $result = new Result(); - $result->initialize($stub, null); - - self::assertEquals($result->current(), $result->current()); - } - - public function testFetchModeException(): void - { - $result = new Result(); - - $this->expectException(InvalidArgumentException::class); - $result->setFetchMode(13); - } - - /** - * Tests whether the fetch mode was set properly and - */ - public function testFetchModeAnonymousObject(): void - { - $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); - $stub->expects($this->any()) - ->method('fetch') - ->willReturnCallback(fn() => new stdClass()); - - $result = new Result(); - $result->initialize($stub, null); - $result->setFetchMode(PDO::FETCH_OBJ); - - self::assertEquals(5, $result->getFetchMode()); - self::assertInstanceOf(stdClass::class, $result->current()); - } - - /** - * Tests whether the fetch mode has a broader range - */ - public function testFetchModeRange(): void - { - $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); - $stub->expects($this->any()) - ->method('fetch') - ->willReturnCallback(fn() => new stdClass()); - $result = new Result(); - $result->initialize($stub, null); - $result->setFetchMode(PDO::FETCH_NAMED); - self::assertEquals(11, $result->getFetchMode()); - self::assertInstanceOf(stdClass::class, $result->current()); - } - - public function testMultipleRewind(): void - { - $data = [ - ['test' => 1], - ['test' => 2], - ]; - $position = 0; - - $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); - $stub->expects($this->any()) - ->method('fetch') - ->willReturnCallback(function () use ($data, &$position) { - return $data[$position++]; - }); - $result = new Result(); - $result->initialize($stub, null); - - $result->rewind(); - $result->rewind(); - - $this->assertEquals(0, $result->key()); - $this->assertEquals(1, $position); - $this->assertEquals($data[0], $result->current()); - - $result->next(); - $this->assertEquals(1, $result->key()); - $this->assertEquals(2, $position); - $this->assertEquals($data[1], $result->current()); - } -} diff --git a/test/unit/Driver/Pdo/StatementTest.php b/test/unit/Driver/Pdo/StatementTest.php deleted file mode 100644 index b107854..0000000 --- a/test/unit/Driver/Pdo/StatementTest.php +++ /dev/null @@ -1,84 +0,0 @@ -statement, - $this->statement->setDriver( - (new PdoDriverFactory())->__invoke( - $this->createMock(ContainerInterface::class) - ) - ) - ); - } - - public function testSetParameterContainer(): void - { - self::assertSame($this->statement, $this->statement->setParameterContainer(new ParameterContainer())); - } - - /** - * @todo Implement testGetParameterContainer(). - */ - public function testGetParameterContainer(): void - { - $container = new ParameterContainer(); - $this->statement->setParameterContainer($container); - self::assertSame($container, $this->statement->getParameterContainer()); - } - - public function testSetSql(): void - { - $this->statement->setSql('SELECT 1'); - self::assertEquals('SELECT 1', $this->statement->getSql()); - } - - public function testGetSql(): void - { - $this->statement->setSql('SELECT 1'); - self::assertEquals('SELECT 1', $this->statement->getSql()); - } - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - #[Override] - protected function setUp(): void - { - $this->statement = new Statement(); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown(): void - { - } -} diff --git a/test/unit/Platform/SqliteTest.php b/test/unit/Platform/SqliteTest.php index ee491ef..fe491fc 100644 --- a/test/unit/Platform/SqliteTest.php +++ b/test/unit/Platform/SqliteTest.php @@ -1,47 +1,65 @@ platform = new Sqlite(new PDO( - dsn: "sqlite::memory:mydb.sqlite", - )); + $pdoMock = $this->createMock(PDO::class); + $this->platform = new Sqlite($pdoMock); + } + + public function testGetNameReturnsSqlite(): void + { + $pdoMock = $this->createMock(PDO::class); + $platform = new Sqlite($pdoMock); + + self::assertSame('SQLite', $platform->getName()); + } + + public function testPlatformNameConstant(): void + { + self::assertSame('SQLite', Sqlite::PLATFORM_NAME); + } + + public function testConstructWithPdo(): void + { + $pdoMock = $this->createMock(PDO::class); + $platform = new Sqlite($pdoMock); + + self::assertInstanceOf(Sqlite::class, $platform); + } + + public function testConstructWithPdoDriver(): void + { + $driverMock = $this->createMock(PdoDriverInterface::class); + $platform = new Sqlite($driverMock); + + self::assertInstanceOf(Sqlite::class, $platform); + } + + public function testGetSqlPlatformDecorator(): void + { + $pdoMock = $this->createMock(PDO::class); + $platform = new Sqlite($pdoMock); + + $decorator = $platform->getSqlPlatformDecorator(); + + self::assertInstanceOf(SqlPlatformDecorator::class, $decorator); } public function testGetName(): void @@ -75,9 +93,6 @@ public function testQuoteValueRaisesNoticeWithoutPlatformSupport(): void { $raisedNotice = false; - /** - * @psalm-suppress InvalidArgument - */ set_error_handler(function (int $errno, string $errstr) use (&$raisedNotice) { $this->assertEquals(E_USER_NOTICE, $errno); $this->assertEquals( @@ -183,28 +198,4 @@ public function testQuoteIdentifierInFragment(): void ) ); } - - public function testCanCloseConnectionAfterQuoteValue(): void - { - // Creating the SQLite database file - $filePath = __DIR__ . "/_files/sqlite.db"; - if (! file_exists($filePath)) { - touch($filePath); - } - - $driver = (new PdoDriverFactory())->__invoke( - $this->createMock(ContainerInterface::class) - ); - - $this->platform->setDriver($driver); - $this->platform->quoteValue("some; random]/ value"); - $this->platform->quoteTrustedValue("some; random]/ value"); - - // Closing the connection so we can delete the file - $driver->getConnection()->disconnect(); - - @unlink($filePath); - - self::assertFileDoesNotExist($filePath); - } } diff --git a/test/unit/Platform/_files/.gitignore b/test/unit/Platform/_files/.gitignore deleted file mode 100644 index c96a04f..0000000 --- a/test/unit/Platform/_files/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/test/unit/Sql/Platform/Ddl/AlterTableDecoratorTest.php b/test/unit/Sql/Platform/Ddl/AlterTableDecoratorTest.php new file mode 100644 index 0000000..331c66d --- /dev/null +++ b/test/unit/Sql/Platform/Ddl/AlterTableDecoratorTest.php @@ -0,0 +1,252 @@ +decorator = new AlterTableDecorator(); + } + + public function testSetSubject(): void + { + $alterTable = new AlterTable('test_table'); + $result = $this->decorator->setSubject($alterTable); + + self::assertSame($this->decorator, $result); + + $reflection = new ReflectionClass($this->decorator); + $subjectProperty = $reflection->getProperty('subject'); + $subject = $subjectProperty->getValue($this->decorator); + + self::assertSame($alterTable, $subject); + } + + public function testColumnOptionSortOrder(): void + { + $reflection = new ReflectionClass($this->decorator); + $sortOrderProperty = $reflection->getProperty('columnOptionSortOrder'); + $sortOrder = $sortOrderProperty->getValue($this->decorator); + + self::assertIsArray($sortOrder); + self::assertArrayHasKey('unsigned', $sortOrder); + self::assertArrayHasKey('zerofill', $sortOrder); + self::assertArrayHasKey('identity', $sortOrder); + self::assertArrayHasKey('serial', $sortOrder); + self::assertArrayHasKey('autoincrement', $sortOrder); + self::assertArrayHasKey('comment', $sortOrder); + self::assertArrayHasKey('columnformat', $sortOrder); + self::assertArrayHasKey('format', $sortOrder); + self::assertArrayHasKey('storage', $sortOrder); + self::assertArrayHasKey('after', $sortOrder); + } + + public function testColumnOptionSortOrderIncludesAfter(): void + { + $reflection = new ReflectionClass($this->decorator); + $sortOrderProperty = $reflection->getProperty('columnOptionSortOrder'); + $sortOrder = $sortOrderProperty->getValue($this->decorator); + + self::assertArrayHasKey('after', $sortOrder); + self::assertSame(6, $sortOrder['after']); + } + + public function testGetSqlInsertOffsets(): void + { + $sql = 'column_name VARCHAR(255) NOT NULL DEFAULT "test" UNIQUE PRIMARY REFERENCES other_table(id)'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertCount(4, $offsets); + self::assertIsInt($offsets[0]); + self::assertIsInt($offsets[1]); + self::assertIsInt($offsets[2]); + self::assertIsInt($offsets[3]); + } + + public function testGetSqlInsertOffsetsWithNullKeyword(): void + { + $sql = 'column_name VARCHAR(255) NULL'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[0]); + } + + public function testGetSqlInsertOffsetsWithDefaultKeyword(): void + { + $sql = 'column_name INTEGER DEFAULT 42'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[0]); + } + + public function testGetSqlInsertOffsetsWithUniqueKeyword(): void + { + $sql = 'column_name VARCHAR(100) UNIQUE'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[1]); + } + + public function testGetSqlInsertOffsetsWithPrimaryKeyword(): void + { + $sql = 'id INTEGER PRIMARY KEY'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[1]); + } + + public function testGetSqlInsertOffsetsWithReferencesKeyword(): void + { + $sql = 'user_id INTEGER REFERENCES users(id)'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[2]); + } + + public function testGetSqlInsertOffsetsWithoutKeywords(): void + { + $sql = 'column_name VARCHAR(255)'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + $sqlLength = strlen($sql); + self::assertSame($sqlLength, $offsets[0]); + self::assertSame($sqlLength, $offsets[1]); + self::assertSame($sqlLength, $offsets[2]); + self::assertSame($sqlLength, $offsets[3]); + } + + public function testNormalizeColumnOption(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('normalizeColumnOption'); + + self::assertSame('autoincrement', $method->invoke($this->decorator, 'auto-increment')); + self::assertSame('autoincrement', $method->invoke($this->decorator, 'auto_increment')); + self::assertSame('autoincrement', $method->invoke($this->decorator, 'AUTO INCREMENT')); + self::assertSame('columnformat', $method->invoke($this->decorator, 'column-format')); + self::assertSame('zerofill', $method->invoke($this->decorator, 'ZERO_FILL')); + self::assertSame('after', $method->invoke($this->decorator, 'AFTER')); + } + + public function testCompareColumnOptions(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + // unsigned (0) should come before zerofill (1) + $result = $method->invoke($this->decorator, 'unsigned', 'zerofill'); + self::assertLessThan(0, $result); + + // zerofill (1) should come before identity (2) + $result = $method->invoke($this->decorator, 'zerofill', 'identity'); + self::assertLessThan(0, $result); + + // identity (2) should come before comment (3) + $result = $method->invoke($this->decorator, 'identity', 'comment'); + self::assertLessThan(0, $result); + + // comment (3) should come before columnformat (4) + $result = $method->invoke($this->decorator, 'comment', 'columnformat'); + self::assertLessThan(0, $result); + + // storage (5) should come before after (6) + $result = $method->invoke($this->decorator, 'storage', 'after'); + self::assertLessThan(0, $result); + } + + public function testCompareColumnOptionsWithSameValue(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + $result = $method->invoke($this->decorator, 'unsigned', 'unsigned'); + self::assertSame(0, $result); + } + + public function testCompareColumnOptionsWithUnknownOptions(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + // Unknown options should be treated equally + $result = $method->invoke($this->decorator, 'unknown1', 'unknown2'); + self::assertSame(0, $result); + } + + public function testCompareColumnOptionsKnownVsUnknown(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + // Known option should come before unknown option + $result = $method->invoke($this->decorator, 'unsigned', 'unknown'); + self::assertLessThan(0, $result); + + // Unknown option should come after known option + $result = $method->invoke($this->decorator, 'unknown', 'unsigned'); + self::assertGreaterThan(0, $result); + } + + public function testCompareColumnOptionsAfterIsLast(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + // 'after' should come after 'storage' + $result = $method->invoke($this->decorator, 'storage', 'after'); + self::assertLessThan(0, $result); + + // 'after' should come after 'comment' + $result = $method->invoke($this->decorator, 'comment', 'after'); + self::assertLessThan(0, $result); + } +} diff --git a/test/unit/Sql/Platform/Ddl/CreateTableDecoratorTest.php b/test/unit/Sql/Platform/Ddl/CreateTableDecoratorTest.php new file mode 100644 index 0000000..96a3323 --- /dev/null +++ b/test/unit/Sql/Platform/Ddl/CreateTableDecoratorTest.php @@ -0,0 +1,226 @@ +decorator = new CreateTableDecorator(); + } + + public function testSetSubject(): void + { + $createTable = new CreateTable('test_table'); + $result = $this->decorator->setSubject($createTable); + + self::assertSame($this->decorator, $result); + + $reflection = new ReflectionClass($this->decorator); + $subjectProperty = $reflection->getProperty('subject'); + $subject = $subjectProperty->getValue($this->decorator); + + self::assertSame($createTable, $subject); + } + + public function testColumnOptionSortOrder(): void + { + $reflection = new ReflectionClass($this->decorator); + $sortOrderProperty = $reflection->getProperty('columnOptionSortOrder'); + $sortOrder = $sortOrderProperty->getValue($this->decorator); + + self::assertIsArray($sortOrder); + self::assertArrayHasKey('unsigned', $sortOrder); + self::assertArrayHasKey('zerofill', $sortOrder); + self::assertArrayHasKey('identity', $sortOrder); + self::assertArrayHasKey('serial', $sortOrder); + self::assertArrayHasKey('autoincrement', $sortOrder); + self::assertArrayHasKey('comment', $sortOrder); + self::assertArrayHasKey('columnformat', $sortOrder); + self::assertArrayHasKey('format', $sortOrder); + self::assertArrayHasKey('storage', $sortOrder); + } + + public function testGetSqlInsertOffsets(): void + { + $sql = 'column_name VARCHAR(255) NOT NULL DEFAULT "test" UNIQUE PRIMARY REFERENCES other_table(id)'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertCount(4, $offsets); + self::assertIsInt($offsets[0]); + self::assertIsInt($offsets[1]); + self::assertIsInt($offsets[2]); + self::assertIsInt($offsets[3]); + } + + public function testGetSqlInsertOffsetsWithNullKeyword(): void + { + $sql = 'column_name VARCHAR(255) NULL'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[0]); + } + + public function testGetSqlInsertOffsetsWithDefaultKeyword(): void + { + $sql = 'column_name INTEGER DEFAULT 42'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[0]); + } + + public function testGetSqlInsertOffsetsWithUniqueKeyword(): void + { + $sql = 'column_name VARCHAR(100) UNIQUE'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[1]); + } + + public function testGetSqlInsertOffsetsWithPrimaryKeyword(): void + { + $sql = 'id INTEGER PRIMARY KEY'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[1]); + } + + public function testGetSqlInsertOffsetsWithReferencesKeyword(): void + { + $sql = 'user_id INTEGER REFERENCES users(id)'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + self::assertGreaterThan(0, $offsets[2]); + } + + public function testGetSqlInsertOffsetsWithoutKeywords(): void + { + $sql = 'column_name VARCHAR(255)'; + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('getSqlInsertOffsets'); + + $offsets = $method->invoke($this->decorator, $sql); + + self::assertIsArray($offsets); + $sqlLength = strlen($sql); + self::assertSame($sqlLength, $offsets[0]); + self::assertSame($sqlLength, $offsets[1]); + self::assertSame($sqlLength, $offsets[2]); + self::assertSame($sqlLength, $offsets[3]); + } + + public function testNormalizeColumnOption(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('normalizeColumnOption'); + + self::assertSame('autoincrement', $method->invoke($this->decorator, 'auto-increment')); + self::assertSame('autoincrement', $method->invoke($this->decorator, 'auto_increment')); + self::assertSame('autoincrement', $method->invoke($this->decorator, 'AUTO INCREMENT')); + self::assertSame('columnformat', $method->invoke($this->decorator, 'column-format')); + self::assertSame('zerofill', $method->invoke($this->decorator, 'ZERO_FILL')); + } + + public function testCompareColumnOptions(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + // unsigned (0) should come before zerofill (1) + $result = $method->invoke($this->decorator, 'unsigned', 'zerofill'); + self::assertLessThan(0, $result); + + // zerofill (1) should come before identity (2) + $result = $method->invoke($this->decorator, 'zerofill', 'identity'); + self::assertLessThan(0, $result); + + // identity (2) should come before comment (3) + $result = $method->invoke($this->decorator, 'identity', 'comment'); + self::assertLessThan(0, $result); + + // comment (3) should come before columnformat (4) + $result = $method->invoke($this->decorator, 'comment', 'columnformat'); + self::assertLessThan(0, $result); + + // storage (5) should come after format (4) + $result = $method->invoke($this->decorator, 'format', 'storage'); + self::assertLessThan(0, $result); + } + + public function testCompareColumnOptionsWithSameValue(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + $result = $method->invoke($this->decorator, 'unsigned', 'unsigned'); + self::assertSame(0, $result); + } + + public function testCompareColumnOptionsWithUnknownOptions(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + // Unknown options should be treated equally + $result = $method->invoke($this->decorator, 'unknown1', 'unknown2'); + self::assertSame(0, $result); + } + + public function testCompareColumnOptionsKnownVsUnknown(): void + { + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('compareColumnOptions'); + + // Known option should come before unknown option + $result = $method->invoke($this->decorator, 'unsigned', 'unknown'); + self::assertLessThan(0, $result); + + // Unknown option should come after known option + $result = $method->invoke($this->decorator, 'unknown', 'unsigned'); + self::assertGreaterThan(0, $result); + } +} diff --git a/test/unit/Sql/Platform/SelectDecoratorTest.php b/test/unit/Sql/Platform/SelectDecoratorTest.php index a0fd91b..309d7ce 100644 --- a/test/unit/Sql/Platform/SelectDecoratorTest.php +++ b/test/unit/Sql/Platform/SelectDecoratorTest.php @@ -4,189 +4,152 @@ namespace PhpDbTest\Adapter\Sqlite\Sql\Platform; -use PhpDb\Adapter\AdapterInterface; use PhpDb\Adapter\Driver\DriverInterface; -use PhpDb\Adapter\Driver\PdoDriverInterface; -use PhpDb\Adapter\Driver\StatementInterface; use PhpDb\Adapter\ParameterContainer; -use PhpDb\Adapter\Sqlite\Platform\Sqlite as SqlitePlatform; +use PhpDb\Adapter\Platform\PlatformInterface; use PhpDb\Adapter\Sqlite\Sql\Platform\SelectDecorator; -use PhpDb\Sql\Expression; use PhpDb\Sql\Select; use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use ReflectionClass; #[CoversClass(SelectDecorator::class)] final class SelectDecoratorTest extends TestCase { - protected SqlitePlatform&MockObject $platform; - protected PdoDriverInterface&MockObject $driver; + private SelectDecorator $decorator; protected function setUp(): void { - $this->driver = $this->getMockBuilder(PdoDriverInterface::class) - ->getMock(); + $this->decorator = new SelectDecorator(); + } + + public function testSetSubject(): void + { + $select = new Select(); + $result = $this->decorator->setSubject($select); + + self::assertSame($this->decorator, $result); - $this->platform = $this->getMockBuilder(SqlitePlatform::class) - ->onlyMethods([]) - ->setConstructorArgs([$this->driver]) - ->getMock(); + $reflection = new ReflectionClass($this->decorator); + $subjectProperty = $reflection->getProperty('subject'); + $subject = $subjectProperty->getValue($this->decorator); - parent::setUp(); + self::assertSame($select, $subject); } - public function testLimitAndOffset(): void + public function testProcessLimitWithoutLimitAndWithoutOffset(): void { - $select = new Select(); - $select->offset(5); - $selectDecorator = new SelectDecorator(); - $selectDecorator->setSubject($select); - $sqlString = $selectDecorator->getSqlString($this->platform); - self::assertEquals('SELECT * LIMIT 18446744073709551615 OFFSET 5', $sqlString); + $platformMock = $this->createMock(PlatformInterface::class); + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('processLimit'); + + $result = $method->invoke($this->decorator, $platformMock); + + self::assertNull($result); } - #[DataProvider('dataProviderUnionSyntaxFromCombine')] - #[TestDox('integration test: Testing SelectDecorator will use Select an internal state to prepare a proper combine -statement')] - public function testPrepareStatementPreparesUnionSyntaxFromCombine( - Select $select, - string $expectedSql, - array $expectedParams - ): void { - $driver = $this->getMockBuilder(DriverInterface::class)->getMock(); - $driver->expects($this->any())->method('formatParameterName')->willReturn('?'); - - // test - $adapter = $this->getMockBuilder(AdapterInterface::class) - ->onlyMethods([]) - ->setConstructorArgs([ - $driver, - $this->platform, - ]) - ->getMock(); + public function testProcessLimitWithLimit(): void + { + $this->decorator->limit(10); - $parameterContainer = new ParameterContainer(); - $statement = $this->getMockBuilder(StatementInterface::class)->getMock(); - $statement->expects($this->any())->method('getParameterContainer') - ->willReturn($parameterContainer); + $platformMock = $this->createMock(PlatformInterface::class); - $statement->expects($this->once())->method('setSql')->with($expectedSql); + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('processLimit'); - $selectDecorator = new SelectDecorator(); - $selectDecorator->setSubject($select); - $selectDecorator->prepareStatement($adapter, $statement); + $result = $method->invoke($this->decorator, $platformMock); - self::assertEquals($expectedParams, $parameterContainer->getNamedArray()); + self::assertSame([10], $result); } - #[DataProvider('dataProviderUnionSyntaxFromCombine')] - #[TestDox('integration test: Testing SelectDecorator will use Select an internal state to prepare a proper combine -statement')] - public function testGetSqlStringPreparesUnionSyntaxFromCombine( - Select $select, - string $expectedSql - ): void { + public function testProcessLimitWithLimitAndParameterContainer(): void + { + $this->decorator->limit(15); + + $platformMock = $this->createMock(PlatformInterface::class); + $driverMock = $this->createMock(DriverInterface::class); + $driverMock->expects(self::once()) + ->method('formatParameterName') + ->with('limit') + ->willReturn(':limit'); + $parameterContainer = new ParameterContainer(); - $statement = $this->getMockBuilder(StatementInterface::class)->getMock(); - $statement->expects($this->any())->method('getParameterContainer') - ->willReturn($parameterContainer); - $selectDecorator = new SelectDecorator(); - $selectDecorator->setSubject($select); - self::assertEquals($expectedSql, $selectDecorator->getSqlString($this->platform)); + $reflection = new ReflectionClass($this->decorator); + $processInfoProperty = $reflection->getProperty('processInfo'); + $processInfoProperty->setValue($this->decorator, ['paramPrefix' => '']); + + $method = $reflection->getMethod('processLimit'); + $result = $method->invoke($this->decorator, $platformMock, $driverMock, $parameterContainer); + + self::assertSame([':limit'], $result); + self::assertTrue($parameterContainer->offsetExists('limit')); + self::assertSame(15, $parameterContainer->offsetGet('limit')); + } + + public function testProcessLimitWithoutLimitButWithOffset(): void + { + $this->decorator->offset(5); + + $platformMock = $this->createMock(PlatformInterface::class); + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('processLimit'); + + $result = $method->invoke($this->decorator, $platformMock); + + self::assertSame([''], $result); } - /** - * Create a data provider for union syntax that would come from combine - * - * @psalm-return array, - * 3: string - * }> - */ - public static function dataProviderUnionSyntaxFromCombine(): array + public function testProcessOffsetWithoutOffset(): void { - $select0 = new Select(); - $select0->from('foo'); - $select1 = clone $select0; - $select0->combine($select1); - - $expectedPrepareSql0 = '( SELECT "foo".* FROM "foo" ) UNION ( SELECT "foo".* FROM "foo" )'; - $expectedParams0 = []; - $expectedSql0 = '( SELECT "foo".* FROM "foo" ) UNION ( SELECT "foo".* FROM "foo" )'; - - // nested single limit & offset in field param - $nestedSelect0 = new Select(); - $nestedSelect0->from('foo1') - ->columns([ - 'cnt' => new Expression('count(foo1.id)'), - ])->limit(100)->offset(500); - - $select3 = new Select(); - $select3->from('foo') - ->columns([ - 'res' => $nestedSelect0, - ]) - ->limit(10)->offset(50); - - $expectedPrepareSql3 = - 'SELECT (SELECT count(foo1.id) AS "cnt" FROM "foo1" LIMIT ? OFFSET ?) AS "res"' - . ' FROM "foo" LIMIT ? OFFSET ?'; - $expectedParams3 = [ - 'subselect1limit' => 100, - 'subselect1offset' => 500, - 'limit' => 10, - 'offset' => 50, - ]; - $expectedSql3 = 'SELECT (SELECT count(foo1.id) AS "cnt"' - . ' FROM "foo1" LIMIT 100 OFFSET 500) AS "res"' - . ' FROM "foo" LIMIT 10 OFFSET 50'; - // multiple nested query - $nestedSelect0 = new Select(); - $nestedSelect0->from('foo1') - ->columns([ - 'cnt' => new Expression('count(foo1.id)'), - ])->limit(100)->offset(500); - - $nestedSelect1 = new Select(); - $nestedSelect1->from('foo2') - ->columns([ - 'cnt' => new Expression('count(foo2.id)'), - ])->limit(50)->offset(101); - - $select4 = new Select(); - $select4->from('foo') - ->columns([ - 'res' => $nestedSelect0, - 'res0' => $nestedSelect1, - ]) - ->limit(10)->offset(5); - - $expectedPrepareSql4 = - 'SELECT (SELECT count(foo1.id) AS "cnt" FROM "foo1" LIMIT ? OFFSET ?) AS "res",' - . ' (SELECT count(foo2.id) AS "cnt" FROM "foo2" LIMIT ? OFFSET ?) AS "res0"' - . ' FROM "foo" LIMIT ? OFFSET ?'; - $expectedParams4 = [ - 'subselect1limit' => 100, - 'subselect1offset' => 500, - 'subselect2limit' => 50, - 'subselect2offset' => 101, - 'limit' => 10, - 'offset' => 5, - ]; - $expectedSql4 = 'SELECT (SELECT count(foo1.id) AS "cnt" FROM "foo1" LIMIT 100 OFFSET 500) AS "res",' - . ' (SELECT count(foo2.id) AS "cnt" FROM "foo2" LIMIT 50 OFFSET 101) AS "res0"' - . ' FROM "foo" LIMIT 10 OFFSET 5'; - - return [ - [$select0, $expectedPrepareSql0, $expectedParams0, $expectedSql0], - [$select3, $expectedPrepareSql3, $expectedParams3, $expectedSql3], - [$select4, $expectedPrepareSql4, $expectedParams4, $expectedSql4], - ]; + $platformMock = $this->createMock(PlatformInterface::class); + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('processOffset'); + + $result = $method->invoke($this->decorator, $platformMock); + + self::assertNull($result); + } + + public function testProcessOffsetWithOffset(): void + { + $this->decorator->offset(20); + + $platformMock = $this->createMock(PlatformInterface::class); + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('processOffset'); + + $result = $method->invoke($this->decorator, $platformMock); + + self::assertSame([20], $result); + } + + public function testProcessOffsetWithOffsetAndParameterContainer(): void + { + $this->decorator->offset(25); + + $platformMock = $this->createMock(PlatformInterface::class); + $driverMock = $this->createMock(DriverInterface::class); + $driverMock->expects(self::once()) + ->method('formatParameterName') + ->with('offset') + ->willReturn(':offset'); + + $parameterContainer = new ParameterContainer(); + + $reflection = new ReflectionClass($this->decorator); + $processInfoProperty = $reflection->getProperty('processInfo'); + $processInfoProperty->setValue($this->decorator, ['paramPrefix' => '']); + + $method = $reflection->getMethod('processOffset'); + $result = $method->invoke($this->decorator, $platformMock, $driverMock, $parameterContainer); + + self::assertSame([':offset'], $result); + self::assertTrue($parameterContainer->offsetExists('offset')); + self::assertSame(25, $parameterContainer->offsetGet('offset')); } } diff --git a/test/unit/Sql/Platform/SqliteTest.php b/test/unit/Sql/Platform/SqliteTest.php index 61feae8..b3676ef 100644 --- a/test/unit/Sql/Platform/SqliteTest.php +++ b/test/unit/Sql/Platform/SqliteTest.php @@ -1,29 +1,62 @@ platform = new Sqlite(); + } + + public function testConstructorSetsTypeDecorators(): void + { + self::assertInstanceOf(Sqlite::class, $this->platform); + } + + public function testSelectDecoratorIsRegistered(): void + { + $reflection = new ReflectionClass($this->platform); + $decoratorsProperty = $reflection->getProperty('decorators'); + $decorators = $decoratorsProperty->getValue($this->platform); + + self::assertArrayHasKey(Select::class, $decorators); + self::assertInstanceOf(SelectDecorator::class, $decorators[Select::class]); + } + + public function testCreateTableDecoratorIsRegistered(): void + { + $reflection = new ReflectionClass($this->platform); + $decoratorsProperty = $reflection->getProperty('decorators'); + $decorators = $decoratorsProperty->getValue($this->platform); + + self::assertArrayHasKey(CreateTable::class, $decorators); + self::assertInstanceOf(CreateTableDecorator::class, $decorators[CreateTable::class]); + } + + public function testAlterTableDecoratorIsRegistered(): void { - $mysql = new Sqlite(); - $decorators = $mysql->getDecorators(); + $reflection = new ReflectionClass($this->platform); + $decoratorsProperty = $reflection->getProperty('decorators'); + $decorators = $decoratorsProperty->getValue($this->platform); - $type = key($decorators); - $decorator = current($decorators); - self::assertEquals(Select::class, $type); - self::assertInstanceOf(SelectDecorator::class, $decorator); + self::assertArrayHasKey(AlterTable::class, $decorators); + self::assertInstanceOf(AlterTableDecorator::class, $decorators[AlterTable::class]); } } diff --git a/test/unit/TestAsset/ConnectionWrapper.php b/test/unit/TestAsset/ConnectionWrapper.php deleted file mode 100644 index 16547d8..0000000 --- a/test/unit/TestAsset/ConnectionWrapper.php +++ /dev/null @@ -1,23 +0,0 @@ -resource = new PdoStubDriver('foo', 'bar', 'baz'); - } - - public function getNestedTransactionsCount(): int - { - return $this->nestedTransactionsCount; - } -} diff --git a/test/unit/TestAsset/PdoStubDriver.php b/test/unit/TestAsset/PdoStubDriver.php deleted file mode 100644 index 1979cb2..0000000 --- a/test/unit/TestAsset/PdoStubDriver.php +++ /dev/null @@ -1,31 +0,0 @@ - Date: Sun, 9 Nov 2025 01:12:20 -0600 Subject: [PATCH 02/11] Add phpstan-baseline.neon file Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- phpstan-baseline.neon | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 phpstan-baseline.neon diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..e69de29 From a017639271fbc2f31481b9abbb993b4eac7f9f7f Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 01:19:58 -0600 Subject: [PATCH 03/11] test new version constraint for phpdb Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9859487..ad6d26c 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ }, "require": { "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "php-db/phpdb": "^0.2.0", + "php-db/phpdb": "<=1.0.0", "webmozart/assert": "^1.11" }, "require-dev": { From 4622e2d2028d6e12f585f874ff30fb746a73c87a Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 01:25:47 -0600 Subject: [PATCH 04/11] Signed-off-by: Joey Smith --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ad6d26c..4dac58e 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ }, "require": { "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "php-db/phpdb": "<=1.0.0", + "php-db/phpdb": "^0.3.0", "webmozart/assert": "^1.11" }, "require-dev": { From 94ef3878d711a8982d787b815b188a537c30072f Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 01:26:29 -0600 Subject: [PATCH 05/11] Signed-off-by: Joey Smith --- composer.lock | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index af94a09..081699a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8e1e64115b9e15d27f9e22c4189baac6", + "content-hash": "373f53734a878eaeebfdde7a145eafda", "packages": [ { "name": "brick/varexporter", @@ -259,22 +259,22 @@ }, { "name": "php-db/phpdb", - "version": "0.2.1", + "version": "0.3.x-dev", "source": { "type": "git", "url": "https://github.com/php-db/phpdb.git", - "reference": "d221b024cb3aea77992f41a962913918301dc92e" + "reference": "c777c58f76533a30b387318f56372ed7922b4c36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-db/phpdb/zipball/d221b024cb3aea77992f41a962913918301dc92e", - "reference": "d221b024cb3aea77992f41a962913918301dc92e", + "url": "https://api.github.com/repos/php-db/phpdb/zipball/c777c58f76533a30b387318f56372ed7922b4c36", + "reference": "c777c58f76533a30b387318f56372ed7922b4c36", "shasum": "" }, "require": { "laminas/laminas-servicemanager": "^4.0.0", "laminas/laminas-stdlib": "^3.20.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "conflict": { "laminas/laminas-db": "*", @@ -292,6 +292,7 @@ "laminas/laminas-eventmanager": "Laminas\\EventManager component", "laminas/laminas-hydrator": "(^5.0.0) Laminas\\Hydrator component for using HydratingResultSets" }, + "default-branch": true, "type": "library", "extra": { "laminas": { @@ -321,7 +322,7 @@ "issues": "https://github.com/php-db/phpdb/issues", "source": "https://github.com/php-db/phpdb" }, - "time": "2025-10-07T08:36:48+00:00" + "time": "2025-11-06T07:40:45+00:00" }, { "name": "psr/container", From ccd76ce3ca632381f73a557fa02ab5942d81d439 Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 01:31:12 -0600 Subject: [PATCH 06/11] phpcs fixes Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- test/unit/AdapterTest.php | 8 ++++---- test/unit/Driver/Pdo/ConnectionTest.php | 3 --- test/unit/Platform/SqliteTest.php | 8 ++++++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/test/unit/AdapterTest.php b/test/unit/AdapterTest.php index 7f96cb0..e67c182 100644 --- a/test/unit/AdapterTest.php +++ b/test/unit/AdapterTest.php @@ -4,6 +4,7 @@ namespace PhpDbTest\Adapter\Sqlite; +use Exception; use Override; use PhpDb\Adapter\Adapter; use PhpDb\Adapter\Driver\DriverInterface; @@ -18,7 +19,6 @@ use PhpDb\ResultSet\ResultSetInterface; use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\Attributes\TestDox; -use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -48,7 +48,7 @@ final class AdapterTest extends TestCase protected Adapter $adapter; /** - * @throws \Exception + * @throws Exception */ #[Override] protected function setUp(): void @@ -105,7 +105,7 @@ public function testGetCurrentSchema(): void } /** - * @throws \Exception + * @throws Exception */ #[TestDox('unit test: Test query() in prepare mode produces a statement object')] public function testQueryWhenPreparedProducesStatement(): void @@ -115,7 +115,7 @@ public function testQueryWhenPreparedProducesStatement(): void } /** - * @throws \Exception + * @throws Exception */ #[TestDox('unit test: Test query() in prepare mode, with array of parameters, produces a result object')] public function testQueryWhenPreparedWithParameterArrayProducesResult(): void diff --git a/test/unit/Driver/Pdo/ConnectionTest.php b/test/unit/Driver/Pdo/ConnectionTest.php index 53beed2..6eab1fb 100644 --- a/test/unit/Driver/Pdo/ConnectionTest.php +++ b/test/unit/Driver/Pdo/ConnectionTest.php @@ -6,14 +6,11 @@ use Exception; use Override; -use PhpDb\Adapter\Exception\InvalidConnectionParametersException; use PhpDb\Adapter\Sqlite\Driver\Pdo\Connection; use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use function realpath; - #[CoversMethod(Connection::class, 'getResource')] #[CoversMethod(Connection::class, 'getDsn')] final class ConnectionTest extends TestCase diff --git a/test/unit/Platform/SqliteTest.php b/test/unit/Platform/SqliteTest.php index fe491fc..90299e9 100644 --- a/test/unit/Platform/SqliteTest.php +++ b/test/unit/Platform/SqliteTest.php @@ -10,7 +10,11 @@ use PhpDb\Adapter\Sqlite\Sql\Platform\Sqlite as SqlPlatformDecorator; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use ReflectionClass; + +use function restore_error_handler; +use function set_error_handler; + +use const E_USER_NOTICE; #[CoversClass(Sqlite::class)] final class SqliteTest extends TestCase @@ -19,7 +23,7 @@ final class SqliteTest extends TestCase protected function setUp(): void { - $pdoMock = $this->createMock(PDO::class); + $pdoMock = $this->createMock(PDO::class); $this->platform = new Sqlite($pdoMock); } From 2f8ec513b6f17c011c52d802b6555539a178e29d Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 01:35:06 -0600 Subject: [PATCH 07/11] Comment incomplete test Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- .../Driver/Pdo/ConnectionIntegrationTest.php | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/test/integration/Driver/Pdo/ConnectionIntegrationTest.php b/test/integration/Driver/Pdo/ConnectionIntegrationTest.php index 088a668..3225ab7 100644 --- a/test/integration/Driver/Pdo/ConnectionIntegrationTest.php +++ b/test/integration/Driver/Pdo/ConnectionIntegrationTest.php @@ -78,42 +78,42 @@ public function testDisconnect(): void /** * @todo Implement testBeginTransaction(). */ - public function testBeginTransaction(): never - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } + // public function testBeginTransaction(): never + // { + // // Remove the following lines when you implement this test. + // $this->markTestIncomplete( + // 'This test has not been implemented yet.' + // ); + // } /** * @todo Implement testCommit(). */ - public function testCommit(): never - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } + // public function testCommit(): never + // { + // // Remove the following lines when you implement this test. + // $this->markTestIncomplete( + // 'This test has not been implemented yet.' + // ); + // } /** * @todo Implement testRollback(). */ - public function testRollback(): never - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - public function testGetLastGeneratedValue(): never - { - $this->markTestIncomplete('Need to create a temporary sequence.'); - //$connection = new Connection($this->variables); - //$connection->getLastGeneratedValue(); - } + // public function testRollback(): never + // { + // // Remove the following lines when you implement this test. + // $this->markTestIncomplete( + // 'This test has not been implemented yet.' + // ); + // } + + // public function testGetLastGeneratedValue(): never + // { + // $this->markTestIncomplete('Need to create a temporary sequence.'); + // //$connection = new Connection($this->variables); + // //$connection->getLastGeneratedValue(); + // } public function testConnectReturnsConnectionWhenResourceSet(): void { From 0e04cf3456e481cd6e705fa89354e284a60599a6 Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 02:12:09 -0600 Subject: [PATCH 08/11] update Connection::getCurrentSchema() to reflect changes in SchemaAwareInterface Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- composer.lock | 8 ++++---- src/Driver/Pdo/Connection.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 081699a..4b5224b 100644 --- a/composer.lock +++ b/composer.lock @@ -263,12 +263,12 @@ "source": { "type": "git", "url": "https://github.com/php-db/phpdb.git", - "reference": "c777c58f76533a30b387318f56372ed7922b4c36" + "reference": "82ccbd942248e55b02d2467939bf6ce6f065a156" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-db/phpdb/zipball/c777c58f76533a30b387318f56372ed7922b4c36", - "reference": "c777c58f76533a30b387318f56372ed7922b4c36", + "url": "https://api.github.com/repos/php-db/phpdb/zipball/82ccbd942248e55b02d2467939bf6ce6f065a156", + "reference": "82ccbd942248e55b02d2467939bf6ce6f065a156", "shasum": "" }, "require": { @@ -322,7 +322,7 @@ "issues": "https://github.com/php-db/phpdb/issues", "source": "https://github.com/php-db/phpdb" }, - "time": "2025-11-06T07:40:45+00:00" + "time": "2025-11-09T08:06:35+00:00" }, { "name": "psr/container", diff --git a/src/Driver/Pdo/Connection.php b/src/Driver/Pdo/Connection.php index dd57722..a7340bb 100644 --- a/src/Driver/Pdo/Connection.php +++ b/src/Driver/Pdo/Connection.php @@ -27,7 +27,7 @@ class Connection extends AbstractPdoConnection * {@inheritDoc} */ #[Override] - public function getCurrentSchema(): string|bool + public function getCurrentSchema(): string|false { if (! $this->isConnected()) { $this->connect(); From 6c53d8a49b01fc58567bc983d9a326480ba7352e Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 02:15:23 -0600 Subject: [PATCH 09/11] Add generated phpstan baseline at level 5 Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- phpstan-baseline.neon | 103 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e69de29..aa4eea9 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -0,0 +1,103 @@ +parameters: + ignoreErrors: + - + message: '#^Variable \$aliasTo on left side of \?\?\= is never defined\.$#' + identifier: nullCoalesce.variable + count: 1 + path: src/Container/DriverInterfaceFactoryFactory.php + + - + message: '#^Cannot call static method createFromConfig\(\) on callable\.$#' + identifier: staticMethod.nonObject + count: 1 + path: src/Container/PdoDriverFactory.php + + - + message: '#^Parameter \#1 \$name \(string\) of method PhpDb\\Adapter\\Sqlite\\Driver\\Pdo\\Connection\:\:getLastGeneratedValue\(\) should be compatible with parameter \$name \(null\) of method PhpDb\\Adapter\\Driver\\ConnectionInterface\:\:getLastGeneratedValue\(\)$#' + identifier: method.childParameterType + count: 2 + path: src/Driver/Pdo/Connection.php + + - + message: '#^Parameter \#2 \$parameters of class PhpDb\\Adapter\\Exception\\InvalidConnectionParametersException constructor expects int, array given\.$#' + identifier: argument.type + count: 1 + path: src/Driver/Pdo/Connection.php + + - + message: '#^Parameter \#1 \$resource \(PDOStatement\) of method PhpDb\\Adapter\\Sqlite\\Driver\\Pdo\\Pdo\:\:createResult\(\) should be compatible with parameter \$resource \(resource\) of method PhpDb\\Adapter\\Driver\\DriverInterface\:\:createResult\(\)$#' + identifier: method.childParameterType + count: 3 + path: src/Driver/Pdo/Pdo.php + + - + message: '#^Parameter \#3 \$rowCount of method PhpDb\\Adapter\\Driver\\Pdo\\Result\:\:initialize\(\) expects int\|null, Closure\|null given\.$#' + identifier: argument.type + count: 1 + path: src/Driver/Pdo/Pdo.php + + - + message: '#^Variable \$schemas might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: src/Metadata/Source/SqliteMetadata.php + + - + message: '#^Method PhpDb\\Adapter\\Sqlite\\Sql\\Platform\\Ddl\\AlterTableDecorator\:\:processAddColumns\(\) should return array\ but returns array\\>\.$#' + identifier: return.type + count: 1 + path: src/Sql/Platform/Ddl/AlterTableDecorator.php + + - + message: '#^Method PhpDb\\Adapter\\Sqlite\\Sql\\Platform\\Ddl\\AlterTableDecorator\:\:processChangeColumns\(\) should return array\ but returns array\\>\>\.$#' + identifier: return.type + count: 1 + path: src/Sql/Platform/Ddl/AlterTableDecorator.php + + - + message: '#^Offset ''paramPrefix'' does not exist on string\.$#' + identifier: offsetAccess.notFound + count: 2 + path: src/Sql/Platform/SelectDecorator.php + + - + message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertIsArray\(\) with array will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType + count: 3 + path: test/unit/ConfigProviderTest.php + + - + message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertIsCallable\(\) with callable\(\)\: mixed will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType + count: 1 + path: test/unit/Container/ConnectionInterfaceFactoryFactoryTest.php + + - + message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertIsCallable\(\) with callable\(\)\: mixed will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType + count: 1 + path: test/unit/Container/DriverInterfaceFactoryFactoryTest.php + + - + message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertIsCallable\(\) with callable\(\)\: mixed will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType + count: 1 + path: test/unit/Container/PlatformInterfaceFactoryFactoryTest.php + + - + message: '#^PHPDoc tag @var with type PhpDb\\Adapter\\Driver\\PdoDriverAwareInterface&PhpDb\\Adapter\\Driver\\StatementInterface is not subtype of native type PHPUnit\\Framework\\MockObject\\MockObject\.$#' + identifier: varTag.nativeType + count: 1 + path: test/unit/Driver/Pdo/PdoTest.php + + - + message: '#^Parameter \#1 \$callback of function set_error_handler expects \(callable\(int, string, string, int\)\: bool\)\|null, Closure\(int, string\)\: void given\.$#' + identifier: argument.type + count: 1 + path: test/unit/Platform/SqliteTest.php + + - + message: '#^Parameter \#1 \$callback of function set_error_handler expects \(callable\(int, string, string, int\)\: bool\)\|null, Closure\(mixed, mixed\)\: void given\.$#' + identifier: argument.type + count: 1 + path: test/unit/Platform/SqliteTest.php From 52b63456bbe26a1b4074eec6a1588841789b50d6 Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 02:18:20 -0600 Subject: [PATCH 10/11] Signed-off-by: Joey Smith --- phpcs.xml.dist | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 38effcf..57d45ca 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -18,10 +18,6 @@ - - + From de099148c37ad55c9b83e5207e0b1d34d11f3ad9 Mon Sep 17 00:00:00 2001 From: Joey Smith Date: Sun, 9 Nov 2025 02:23:27 -0600 Subject: [PATCH 11/11] phpcs fixes Signed-off-by: Joey Smith Signed-off-by: Joey Smith --- src/Sql/Platform/Ddl/AlterTableDecorator.php | 2 + src/Sql/Platform/Ddl/CreateTableDecorator.php | 2 + src/Sql/Platform/SelectDecorator.php | 2 + src/Sql/Platform/Sqlite.php | 2 + .../Driver/Pdo/AbstractAdapterTestCase.php | 2 + .../Driver/Pdo/ConnectionIntegrationTest.php | 39 +++++++------------ 6 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/Sql/Platform/Ddl/AlterTableDecorator.php b/src/Sql/Platform/Ddl/AlterTableDecorator.php index 568efea..0b975f7 100644 --- a/src/Sql/Platform/Ddl/AlterTableDecorator.php +++ b/src/Sql/Platform/Ddl/AlterTableDecorator.php @@ -1,5 +1,7 @@ isConnected()); } - /** - * @todo Implement testBeginTransaction(). - */ + public function testConnectReturnsConnectionWhenResourceSet(): void + { + /** @var PDO $resource */ + $resource = $this->getAdapter()->getDriver()->getConnection()->getResource(); + /** @var PdoConnectionInterface&Connection $connection */ + $connection = $this->getAdapter()->getDriver()->getConnection(); + self::assertInstanceOf(PdoConnectionInterface::class, $connection); + $connection->setResource($resource); + self::assertSame($connection, $connection->connect()); + + $connection->disconnect(); + unset($connection); + unset($resource); + } + // public function testBeginTransaction(): never // { // // Remove the following lines when you implement this test. @@ -86,9 +98,6 @@ public function testDisconnect(): void // ); // } - /** - * @todo Implement testCommit(). - */ // public function testCommit(): never // { // // Remove the following lines when you implement this test. @@ -97,9 +106,6 @@ public function testDisconnect(): void // ); // } - /** - * @todo Implement testRollback(). - */ // public function testRollback(): never // { // // Remove the following lines when you implement this test. @@ -114,19 +120,4 @@ public function testDisconnect(): void // //$connection = new Connection($this->variables); // //$connection->getLastGeneratedValue(); // } - - public function testConnectReturnsConnectionWhenResourceSet(): void - { - /** @var PDO $resource */ - $resource = $this->getAdapter()->getDriver()->getConnection()->getResource(); - /** @var PdoConnectionInterface&Connection $connection */ - $connection = $this->getAdapter()->getDriver()->getConnection(); - self::assertInstanceOf(PdoConnectionInterface::class, $connection); - $connection->setResource($resource); - self::assertSame($connection, $connection->connect()); - - $connection->disconnect(); - unset($connection); - unset($resource); - } }