Skip to content

Commit

Permalink
More tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Girgias committed Jan 8, 2025
1 parent 4829f66 commit 69ea9ab
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 173 deletions.
136 changes: 136 additions & 0 deletions ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
--TEST--
PDO Common: Set PDOStatement class with PDO::ATTR_STATEMENT_CLASS overall test
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';

$db = PDOTest::factory();
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);

$table = 'pdo_attr_statement_class_basic';
$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))");
$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')");
$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')");
$db->exec("INSERT INTO {$table} (id, label) VALUES (3, 'c')");
$db->exec("INSERT INTO {$table} (id, label) VALUES (4, 'd')");
$db->exec("INSERT INTO {$table} (id, label) VALUES (5, 'e')");
$db->exec("INSERT INTO {$table} (id, label) VALUES (6, 'f')");

$default = $db->getAttribute(PDO::ATTR_STATEMENT_CLASS);
var_dump($default);

// Having a public destructor is allowed
class StatementWithPublicDestructor extends PDOStatement {
public function __destruct() {
echo __METHOD__, PHP_EOL;
}
}

try {
var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementWithPublicDestructor', []]));
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementWithPublicDestructor']));
$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2");
unset($stmt);

echo "Class derived from PDOStatement, with private constructor:\n";
class StatementWithPrivateConstructor extends PDOStatement {
private function __construct($msg) {
echo __METHOD__, PHP_EOL;
var_dump($this);
var_dump($msg);
}
}
var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementWithPrivateConstructor', ['param1']]));
$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2");
unset($stmt);

echo "Class derived from a child of PDOStatement:\n";
class StatementDerivedFromChild extends StatementWithPrivateConstructor {
public function fetchAll($fetch_style = 1, ...$fetch_args): array {
return [];
}
}

var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['StatementDerivedFromChild', ['param1']]));
$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2");
var_dump($stmt->fetchAll());
unset($stmt);

echo "Reset to default PDOStatement class:\n";
var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['PDOStatement']));
$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2");
var_dump($stmt->fetchAll());
unset($stmt);

?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_attr_statement_class_basic");
?>
--EXPECT--
array(1) {
[0]=>
string(12) "PDOStatement"
}
bool(true)
bool(true)
StatementWithPublicDestructor::__destruct
Class derived from PDOStatement, with private constructor:
bool(true)
StatementWithPrivateConstructor::__construct
object(StatementWithPrivateConstructor)#2 (1) {
["queryString"]=>
string(76) "SELECT id, label FROM pdo_attr_statement_class_basic ORDER BY id ASC LIMIT 2"
}
string(6) "param1"
Class derived from a child of PDOStatement:
bool(true)
StatementWithPrivateConstructor::__construct
object(StatementDerivedFromChild)#2 (1) {
["queryString"]=>
string(76) "SELECT id, label FROM pdo_attr_statement_class_basic ORDER BY id ASC LIMIT 2"
}
string(6) "param1"
array(0) {
}
Reset to default PDOStatement class:
bool(true)
array(2) {
[0]=>
array(4) {
["id"]=>
string(1) "1"
[0]=>
string(1) "1"
["label"]=>
string(1) "a"
[1]=>
string(1) "a"
}
[1]=>
array(4) {
["id"]=>
string(1) "2"
[0]=>
string(1) "2"
["label"]=>
string(1) "b"
[1]=>
string(1) "b"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
--TEST--
PDO Common: Set PDOStatement class with PDO::ATTR_STATEMENT_CLASS various error conditions
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';

$db = PDOTest::factory();

try {
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'not an array');
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}

echo "Unknown class variation:\n";
try {
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname']);
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}

try {
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname', []]);
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}

echo "Class not derived from PDOStatement:\n";
class NotDerived {
}

try {
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['NotDerived']);
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
try {
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['NotDerived', []]);
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}

echo "Class derived from PDOStatement, but with public constructor:\n";
class DerivedWithPublicConstructor extends PDOStatement {
public function __construct() { }
}

try {
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['DerivedWithPublicConstructor']);
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
try {
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['DerivedWithPublicConstructor', []]);
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
?>
--EXPECT--
TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, string given
Unknown class variation:
TypeError: PDO::ATTR_STATEMENT_CLASS class must be a valid class
TypeError: PDO::ATTR_STATEMENT_CLASS class must be a valid class
Class not derived from PDOStatement:
TypeError: PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement
TypeError: PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement
Class derived from PDOStatement, but with public constructor:
TypeError: User-supplied statement class cannot have a public constructor
TypeError: User-supplied statement class cannot have a public constructor
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
PDO Common: Set PDOStatement class with PDO::ATTR_STATEMENT_CLASS that is abstract
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';

$db = PDOTest::factory();
$table = 'pdo_attr_statement_class_abstract';
$db->exec("CREATE TABLE {$table} (id INT, label CHAR(1), PRIMARY KEY(id))");
$db->exec("INSERT INTO {$table} (id, label) VALUES (1, 'a')");
$db->exec("INSERT INTO {$table} (id, label) VALUES (2, 'b')");

abstract class DerivedButAbstract extends PDOStatement {
private function __construct() {}
}

try {
var_dump($db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['DerivedButAbstract', ['DerivedButAbstract']]));
$stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 1");
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_attr_statement_class_abstract");
?>
--EXPECT--
bool(true)
Error: Cannot instantiate abstract class DerivedButAbstract
2 changes: 1 addition & 1 deletion ext/pdo/tests/pdo_test.inc
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function get_dummy_sql_request(): string

// Firebird: https://www.firebirdfaq.org/faq30/
if (str_starts_with($dsn, 'firebird')) {
return 'SELECT current_timestamp FROM RDB$DATABASE';
return "SELECT FIRST 0 FROM (VALUES ('Hello world')";
}

// Oracle
Expand Down
Loading

0 comments on commit 69ea9ab

Please sign in to comment.