Skip to content

[Tests] Optimized pdo_odbc tests #12654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions ext/pdo_odbc/tests/basic_connection.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@ Basic test for connection. (When not using a DSN alias)
pdo_odbc
--SKIPIF--
<?php
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
$dsn = getenv('PDO_ODBC_TEST_DSN');
if (!$dsn || strpos($dsn, '=') === false) {
die('skip');
}
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skipNoDirect();
ODBCPDOTest::skipToofewCredentials();
ODBCPDOTest::skip();
?>
--XLEAK--
A bug in msodbcsql causes a memory leak when reconnecting after closing. See GH-12306
--FILE--
<?php
$dsnWithCredentials = getenv('PDO_ODBC_TEST_DSN');
$user = getenv('PDO_ODBC_TEST_USER');
$password = getenv('PDO_ODBC_TEST_PASS');
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$dsnWithCredentials = PDO_ODBC_TEST_DSN;
$user = PDO_ODBC_TEST_USER;
$password = PDO_ODBC_TEST_PASS;

$dsn = str_replace(";uid={$user};pwd={$password}", '', $dsnWithCredentials);

Expand Down
8 changes: 4 additions & 4 deletions ext/pdo_odbc/tests/bug44643.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ Bug #44643 (bound parameters ignore explicit type definitions)
pdo_odbc
--SKIPIF--
<?php
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skip();
?>
--FILE--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$sql = "SELECT * FROM (SELECT 'test' = :id1) a WHERE a.test = :id2";
$stmt = $db->prepare($sql);
$id1 = 1;
Expand Down
8 changes: 4 additions & 4 deletions ext/pdo_odbc/tests/bug67465.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ Bug #67465 (NULL Pointer dereference in odbc_handle_preparer)
pdo_odbc
--SKIPIF--
<?php
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skip();
?>
--FILE--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$db->prepare("SELECT 1", [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
echo "done\n";
?>
Expand Down
23 changes: 13 additions & 10 deletions ext/pdo_odbc/tests/bug80783.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
pdo_odbc
--SKIPIF--
<?php
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skip();
?>
--FILE--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("CREATE TABLE bug80783 (name IMAGE)");
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();

$table_name = 'bug80783_pdo_odbc';

$db->exec("CREATE TABLE {$table_name} (name IMAGE)");

$string = str_repeat("0123456789", 50);
$db->exec("INSERT INTO bug80783 VALUES('$string')");
$db->exec("INSERT INTO {$table_name} VALUES('$string')");

$stmt = $db->prepare("SELECT name FROM bug80783");
$stmt = $db->prepare("SELECT name FROM {$table_name}");
$stmt->bindColumn(1, $data, PDO::PARAM_LOB);
$stmt->execute();
$stmt->fetch(PDO::FETCH_BOUND);
Expand All @@ -25,9 +28,9 @@ var_dump($data === bin2hex($string));
?>
--CLEAN--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("DROP TABLE IF EXISTS bug80783");
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$db->exec("DROP TABLE IF EXISTS bug80783_pdo_odbc");
?>
--EXPECT--
bool(true)
29 changes: 14 additions & 15 deletions ext/pdo_odbc/tests/bug80783a.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@ Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
pdo_odbc
--SKIPIF--
<?php

require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();

if (PDO_ODBC_TYPE === "unixODBC") {
die("skip Fails with unixODBC");
}
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skipWithUnixODBC();
ODBCPDOTest::skip();
?>
--FILE--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("CREATE TABLE bug80783a (name NVARCHAR(MAX))");
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();

$table_name = 'bug80783a_pdo_odbc';

$db->exec("CREATE TABLE {$table_name} (name NVARCHAR(MAX))");

$string = str_repeat("0123456789", 50);
$db->exec("INSERT INTO bug80783a VALUES('$string')");
$db->exec("INSERT INTO {$table_name} VALUES('$string')");

$stmt = $db->prepare("SELECT name FROM bug80783a");
$stmt = $db->prepare("SELECT name FROM {$table_name}");
$stmt->setAttribute(PDO::ODBC_ATTR_ASSUME_UTF8, true);
$stmt->bindColumn(1, $data, PDO::PARAM_STR);
$stmt->execute();
Expand All @@ -31,9 +30,9 @@ var_dump($data === $string);
?>
--CLEAN--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("DROP TABLE IF EXISTS bug80783a");
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$db->exec("DROP TABLE IF EXISTS bug80783a_pdo_odbc");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General comment on the pattern: I like removing the hardcoded table names from the query strings. It’s a little annoying that it has to be hardcoded here after it was unhardcoded for all the tests in their FILE sections, but I see why you probably didn’t do it for CLEAN (it’d be an ugly use of ENV/ARGS, and I’m not sure if those get propagated to CLEAN to begin with).

?>
--EXPECT--
bool(true)
8 changes: 4 additions & 4 deletions ext/pdo_odbc/tests/get_attribute_server.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ PDO ODBC getAttribute SERVER_INFO and SERVER_VERSION
pdo_odbc
--SKIPIF--
<?php
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skip();
?>
--FILE--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory('ext/pdo_odbc/tests/common.phpt');
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
// Obviously, we can't assume what driver is being used, so just check strings
// Example driver output (MariaDB ODBC):
// PDO::ATTR_SERVER_INFO: MariaDB
Expand Down
24 changes: 13 additions & 11 deletions ext/pdo_odbc/tests/gh9372.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ Bug GH-9372 (HY010 when binding overlong parameter)
pdo_odbc
--SKIPIF--
<?php
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skip();
?>
--FILE--
<?php
// Executing the statements fails with some drivers, but not others.
// The test is written in a way to always pass, unless the execution
// fails with a different code than 22001 (String data, right truncation).

require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$db->exec("CREATE TABLE gh9372 (col VARCHAR(10))");
$db->exec("INSERT INTO gh9372 VALUES ('something')");
$table_name = 'gh9372_pdo_odbc';

$stmt = $db->prepare("SELECT * FROM gh9372 WHERE col = ?");
$db->exec("CREATE TABLE {$table_name} (col VARCHAR(10))");
$db->exec("INSERT INTO {$table_name} VALUES ('something')");

$stmt = $db->prepare("SELECT * FROM {$table_name} WHERE col = ?");
$stmt->bindValue(1, 'something else');
try {
$stmt->execute();
Expand All @@ -30,7 +32,7 @@ try {
}
}

$stmt = $db->prepare("SELECT * FROM gh9372 WHERE col = ?");
$stmt = $db->prepare("SELECT * FROM {$table_name} WHERE col = ?");
$stream = fopen("php://memory", "w+");
fwrite($stream, 'something else');
rewind($stream);
Expand All @@ -45,8 +47,8 @@ try {
?>
--CLEAN--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("DROP TABLE gh9372");
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$db->exec("DROP TABLE IF EXISTS gh9372_pdo_odbc");
?>
--EXPECT--
30 changes: 30 additions & 0 deletions ext/pdo_odbc/tests/inc/config.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
$env = [
'PDO_ODBC_TEST_DSN' => false !== getenv('PDO_ODBC_TEST_DSN') ? getenv('PDO_ODBC_TEST_DSN') : '',
'PDO_ODBC_TEST_USER' => false !== getenv('PDO_ODBC_TEST_USER') ? getenv('PDO_ODBC_TEST_USER') : null,
'PDO_ODBC_TEST_PASS' => false !== getenv('PDO_ODBC_TEST_PASS') ? getenv('PDO_ODBC_TEST_PASS') : null,
'PDO_ODBC_TEST_ATTR' => false !== getenv('PDO_ODBC_TEST_ATTR') ? getenv('PDO_ODBC_TEST_ATTR') : null,
];

if (!$env['PDO_ODBC_TEST_DSN'] && preg_match('/^WIN/i', PHP_OS) && extension_loaded('com_dotnet')) {
// on Windows and user didn't set PDOTEST_DSN, try this as a fallback:
// check if MS Access DB is installed, and if yes, try using it. create a temporary MS access database.

$path = realpath(__DIR__) . '\..\pdo_odbc.mdb';
if (!file_exists($path)) {
try {
// try to create database
$adox = new COM('ADOX.Catalog');
$adox->Create('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=' . $path);
$adox = null;

} catch (Exception $e) {
// do nothing
}
}
if (file_exists($path)) {
// database was created and written to file system
$env['PDO_ODBC_TEST_DSN'] = 'odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=$path;Uid=Admin';
}
}
?>
65 changes: 65 additions & 0 deletions ext/pdo_odbc/tests/inc/odbc_pdo_test.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
require_once __DIR__ . '/config.inc';
require_once __DIR__ . '/../../../../ext/pdo/tests/pdo_test.inc';

foreach ($env as $k => $v) {
define($k, $v);
}

class ODBCPDOTest extends PDOTest {

static function factory($classname = 'PDO') {
$dsn = PDO_ODBC_TEST_DSN;
$user = PDO_ODBC_TEST_USER;
$pass = PDO_ODBC_TEST_PASS;
$attr = PDO_ODBC_TEST_ATTR;

$attr = is_string($attr) && strlen($attr) ? unserialize($attr) : null;

$db = new $classname($dsn, $user, $pass, $attr);
if (!$db) {
die("Could not create PDO object (DSN=$dsn, user=$user)\n");
}

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);

return $db;
}

static function skip() {
if (substr(PHP_OS, 0, 3) == 'WIN' &&
PDO_ODBC_TEST_DSN === '' &&
!extension_loaded('com_dotnet')
) {
die('skip - either PDOTEST_DSN or com_dotnet extension is needed to setup the connection');
}

try {
$db = self::factory();
} catch (PDOException $e) {
die('skip could not connect');
}
Comment on lines +39 to +43
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to eventually make parent skip like this, but the scope is too wide, so I won't change it yet in this PR.

}

static function skipWithUnixODBC() {
if (PDO_ODBC_TYPE === "unixODBC") {
die("skip Fails with unixODBC");
}
}

static function skipNoDirect() {
$dsn = PDO_ODBC_TEST_DSN;
if (!$dsn || strpos($dsn, '=') === false) {
die('skip this test is for direct connections only.');
}
}

static function skipToofewCredentials() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: should be skipTooFewCredentials

if (PDO_ODBC_TEST_DSN === '' || PDO_ODBC_TEST_USER === null || PDO_ODBC_TEST_PASS === null) {
die('skip too few credentials.');
}
}
}
?>
28 changes: 14 additions & 14 deletions ext/pdo_odbc/tests/long_columns.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ PDO ODBC "long" columns
pdo_odbc
--SKIPIF--
<?php
// make sure there is an ODBC driver and a DSN, or the test will fail
include 'ext/pdo/tests/pdo_test.inc';
$config = PDOTest::get_config('ext/pdo_odbc/tests/common.phpt');
if (!isset($config['ENV']['PDOTEST_DSN']) || $config['ENV']['PDOTEST_DSN']===false) print 'skip';
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
ODBCPDOTest::skip();
?>
--FILE--
<?php
Expand Down Expand Up @@ -42,13 +40,15 @@ if (!isset($config['ENV']['PDOTEST_DSN']) || $config['ENV']['PDOTEST_DSN']===fal
// configure --disable-all --enable-cli --enable-pdo --with-pdo-odbc=unixODBC,/usr,/usr --with-unixODBC=/usr --enable-debug
//

require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory('ext/pdo_odbc/tests/common.phpt');
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);

if (false === $db->exec('CREATE TABLE test_long_columns (id INT NOT NULL PRIMARY KEY, data CLOB)')) {
if (false === $db->exec('CREATE TABLE test_long_columns (id INT NOT NULL PRIMARY KEY, data longtext)')) {
if (false === $db->exec('CREATE TABLE test_long_columns (id INT NOT NULL PRIMARY KEY, data varchar(4000))')) {
$table_name = 'test_long_columns_pdo_odbc';

if (false === $db->exec("CREATE TABLE {$table_name} (id INT NOT NULL PRIMARY KEY, data CLOB)")) {
if (false === $db->exec("CREATE TABLE {$table_name} (id INT NOT NULL PRIMARY KEY, data longtext)")) {
if (false === $db->exec("CREATE TABLE {$table_name} (id INT NOT NULL PRIMARY KEY, data varchar(4000))")) {
die("BORK: don't know how to create a long column here:\n" . implode(", ", $db->errorInfo()));
}
}
Expand All @@ -74,11 +74,11 @@ function alpha_repeat($len) {
// this test does - nice to be able to test using MS SQL server
foreach ($sizes as $num) {
$text = alpha_repeat($num);
$db->exec("INSERT INTO test_long_columns VALUES($num, '$text')");
$db->exec("INSERT INTO {$table_name} VALUES($num, '$text')");
}

// verify data
foreach ($db->query('SELECT id, data from test_long_columns ORDER BY LEN(data) ASC') as $row) {
foreach ($db->query("SELECT id, data FROM {$table_name} ORDER BY LEN(data) ASC") as $row) {
$expect = alpha_repeat($row[0]);
if (strcmp($expect, $row[1])) {
echo "Failed on size $row[id]:\n";
Expand All @@ -94,9 +94,9 @@ echo "Finished\n";
?>
--CLEAN--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("DROP TABLE IF EXISTS test_long_columns");
require_once __DIR__ . '/inc/odbc_pdo_test.inc';
$db = ODBCPDOTest::factory();
$db->exec("DROP TABLE IF EXISTS test_long_columns_pdo_odbc");
?>
--EXPECT--
Passed on size 32
Expand Down
Loading