driver = new PdoDriver($config); try { $this->driver->pdo(); } catch (MyException $e) { $this->markTestSkipped('Нет живого подключения к MariaDB (заполните App/config/config.local.php): ' . $e->getMessage()); } $this->driver->exec('DROP TABLE IF EXISTS pdo_driver_test'); $this->driver->exec('CREATE TABLE pdo_driver_test (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))'); } protected function tearDown(): void { Profiler::reset(); if (isset($this->driver)) { try { $this->driver->exec('DROP TABLE IF EXISTS pdo_driver_test'); } catch (MyException) { // соединения не было — нечего дропать } } } public function testFailoverThrowsWithAllHostErrors(): void { // Чисто логика failover — не требует живой БД, оба хоста заведомо недоступны $driver = new PdoDriver(['hosts' => ['bad-host-1', 'bad-host-2'], 'dbname' => 'x', 'user' => 'x', 'password' => 'x']); try { $driver->pdo(); $this->fail('Ожидалось MyException'); } catch (MyException $e) { $this->assertStringContainsString('bad-host-1', $e->getMessage()); $this->assertStringContainsString('bad-host-2', $e->getMessage()); } } public function testQueryInsertsAndSelects(): void { $this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['foo']); $row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['foo'])->fetch(); $this->assertSame('foo', $row['name']); } public function testLastInsertId(): void { $this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['foo']); $this->assertNotFalse($this->driver->lastInsertId()); } public function testCommitPersistsChanges(): void { $this->driver->beginTransaction(); $this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['committed']); $this->driver->commit(); $row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['committed'])->fetch(); $this->assertNotFalse($row); } public function testRollbackDiscardsChanges(): void { $this->driver->beginTransaction(); $this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['rolled_back']); $this->driver->rollback(); $row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['rolled_back'])->fetch(); $this->assertFalse($row); } public function testNestedTransactionRollbackDoesNotAffectOuter(): void { $this->driver->beginTransaction(); $this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['outer']); $this->driver->beginTransaction(); // SAVEPOINT sp_1 $this->driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['inner']); $this->driver->rollback(); // ROLLBACK TO SAVEPOINT sp_1 — не трогает 'outer' $this->driver->commit(); // фиксирует внешнюю транзакцию $outer = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['outer'])->fetch(); $inner = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['inner'])->fetch(); $this->assertNotFalse($outer); $this->assertFalse($inner); } public function testTransactionHelperRollsBackOnException(): void { try { $this->driver->transaction(function (PdoDriver $driver) { $driver->query('INSERT INTO pdo_driver_test (name) VALUES (?)', ['should_rollback']); throw new \RuntimeException('boom'); }); $this->fail('Ожидалось RuntimeException'); } catch (\RuntimeException) { // ожидаемо } $row = $this->driver->query('SELECT * FROM pdo_driver_test WHERE name = ?', ['should_rollback'])->fetch(); $this->assertFalse($row); } public function testInTransaction(): void { $this->assertFalse($this->driver->inTransaction()); $this->driver->beginTransaction(); $this->assertTrue($this->driver->inTransaction()); $this->driver->commit(); $this->assertFalse($this->driver->inTransaction()); } }