From ee846c461c6f0d4ec02dcefa6c82090587bc7012 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 22 Oct 2010 19:11:18 +0200 Subject: [PATCH 1/9] [task/mssql-db-tests] Use a simple getter for test case helpers. Calling initialisation to then use the member directly seems more complicated than just having a method that returns the instance or creates it if necessary. PHPBB3-9868 --- tests/test_framework/phpbb_database_test_case.php | 13 ++++++------- tests/test_framework/phpbb_test_case.php | 7 ++++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index f6bf420ebc..c183c61f91 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -11,12 +11,14 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test { protected $test_case_helpers; - public function init_test_case_helpers() + public function get_test_case_helpers() { if (!$this->test_case_helpers) { $this->test_case_helpers = new phpbb_test_case_helpers($this); } + + return $this->test_case_helpers; } public function get_dbms_data($dbms) @@ -113,8 +115,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test { static $already_connected; - $this->init_test_case_helpers(); - $database_config = $this->test_case_helpers->get_database_config(); + $database_config = $this->get_test_case_helpers()->get_database_config(); $dbms_data = $this->get_dbms_data($database_config['dbms']); @@ -189,13 +190,11 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test public function new_dbal() { - $this->init_test_case_helpers(); - return $this->test_case_helpers->new_dbal(); + return $this->get_test_case_helpers()->new_dbal(); } public function setExpectedTriggerError($errno, $message = '') { - $this->init_test_case_helpers(); - $this->test_case_helpers->setExpectedTriggerError($errno, $message); + $this->get_test_case_helpers()->setExpectedTriggerError($errno, $message); } } diff --git a/tests/test_framework/phpbb_test_case.php b/tests/test_framework/phpbb_test_case.php index af867b29ff..fe90d321dc 100644 --- a/tests/test_framework/phpbb_test_case.php +++ b/tests/test_framework/phpbb_test_case.php @@ -11,17 +11,18 @@ class phpbb_test_case extends PHPUnit_Framework_TestCase { protected $test_case_helpers; - public function init_test_case_helpers() + public function get_test_case_helpers() { if (!$this->test_case_helpers) { $this->test_case_helpers = new phpbb_test_case_helpers($this); } + + return $this->test_case_helpers; } public function setExpectedTriggerError($errno, $message = '') { - $this->init_test_case_helpers(); - $this->test_case_helpers->setExpectedTriggerError($errno, $message); + $this->get_test_case_helpers()->setExpectedTriggerError($errno, $message); } } From 9dbbfea5fd31e40acc6fb4a195795b3e285a5b56 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 22 Oct 2010 19:27:41 +0200 Subject: [PATCH 2/9] [task/mssql-db-tests] No longer display an error when skipping db tests. Tests are run with sqlite by default now anyway, so in the majority of cases the error message explaining how to set up database test running will not be displayed anyway. Database tests are now generally simply skipped if no configuration can be found. The RUNNING_TESTS.txt file explains how to set them up however, and more info is available on the wiki. The get_database_config method was moved from test_case_helpers to database_test_case because it has no general purpose. PHPBB3-9868 --- tests/RUNNING_TESTS.txt | 30 ++++++-- .../phpbb_database_test_case.php | 48 ++++++++++++- .../phpbb_test_case_helpers.php | 68 ------------------- 3 files changed, 70 insertions(+), 76 deletions(-) diff --git a/tests/RUNNING_TESTS.txt b/tests/RUNNING_TESTS.txt index f1b40f71ad..a5d3111242 100644 --- a/tests/RUNNING_TESTS.txt +++ b/tests/RUNNING_TESTS.txt @@ -1,33 +1,51 @@ Running Tests -------------- +============= Prerequisites -------------- +============= PHPUnit -======= +------- phpBB unit tests use PHPUnit framework. Version 3.3 or better is required to run the tests. PHPUnit prefers to be installed via PEAR; refer to http://www.phpunit.de/ for more information. PHP extensions -============== +-------------- Unit tests use several PHP extensions that board code does not use. Currently the following PHP extensions must be installed and enabled to run unit tests: - ctype +Database Tests +-------------- +By default all tests requiring a database connection will use sqlite. If you +do not have sqlite installed the tests will be skipped. If you wish to run the +tests on a different database you have to create a test_config.php file within +your tests directory following the same format as phpBB's config.php. An example +for mysqli can be found below. More information on configuration options can be +found on the wiki (see below). + + $dbms, + 'dbhost' => $dbhost, + 'dbport' => $dbport, + 'dbname' => $dbname, + 'dbuser' => $dbuser, + 'dbpasswd' => $dbpasswd, + ); + } + else if (extension_loaded('sqlite') && version_compare(PHPUnit_Runner_Version::id(), '3.4.15', '>=')) + { + // Silently use sqlite + return array( + 'dbms' => 'sqlite', + 'dbhost' => 'phpbb_unit_tests.sqlite2', // filename + 'dbport' => '', + 'dbname' => '', + 'dbuser' => '', + 'dbpasswd' => '', + ); + } + else + { + $this->markTestSkipped('Missing test_config.php: See first error.'); + } + } + // NOTE: This function is not the same as split_sql_file from functions_install public function split_sql_file($sql, $dbms) { @@ -115,7 +150,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test { static $already_connected; - $database_config = $this->get_test_case_helpers()->get_database_config(); + $database_config = $this->get_database_config(); $dbms_data = $this->get_dbms_data($database_config['dbms']); @@ -190,7 +225,16 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test public function new_dbal() { - return $this->get_test_case_helpers()->new_dbal(); + global $phpbb_root_path, $phpEx; + + $config = $this->get_database_config(); + + require_once '../phpBB/includes/db/' . $config['dbms'] . '.php'; + $dbal = 'dbal_' . $config['dbms']; + $db = new $dbal(); + $db->sql_connect($config['dbhost'], $config['dbuser'], $config['dbpasswd'], $config['dbname'], $config['dbport']); + + return $db; } public function setExpectedTriggerError($errno, $message = '') diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 7c026e496e..0acdce32e0 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -18,74 +18,6 @@ class phpbb_test_case_helpers $this->test_case = $test_case; } - public function get_database_config() - { - static $show_error = true; - - if (file_exists('test_config.php')) - { - include('test_config.php'); - - return array( - 'dbms' => $dbms, - 'dbhost' => $dbhost, - 'dbport' => $dbport, - 'dbname' => $dbname, - 'dbuser' => $dbuser, - 'dbpasswd' => $dbpasswd, - ); - } - else if (extension_loaded('sqlite') && version_compare(PHPUnit_Runner_Version::id(), '3.4.15', '>=')) - { - // Silently use sqlite - return array( - 'dbms' => 'sqlite', - 'dbhost' => 'phpbb_unit_tests.sqlite2', // filename - 'dbport' => '', - 'dbname' => '', - 'dbuser' => '', - 'dbpasswd' => '', - ); - } - else - { - if ($show_error) - { - $show_error = false; - } - else - { - $this->test_case->markTestSkipped('Missing test_config.php: See first error.'); - return; - } - - trigger_error("You have to create a test_config.php like this: -\"get_database_config(); - - require_once '../phpBB/includes/db/' . $config['dbms'] . '.php'; - $dbal = 'dbal_' . $config['dbms']; - $db = new $dbal(); - $db->sql_connect($config['dbhost'], $config['dbuser'], $config['dbpasswd'], $config['dbname'], $config['dbport']); - - return $db; - } - public function setExpectedTriggerError($errno, $message = '') { $exceptionName = ''; From a397f81a2bc03019910c088376cf563d05dadf93 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 22 Oct 2010 19:50:43 +0200 Subject: [PATCH 3/9] [task/mssql-db-tests] Allow test configuration with environment variables. To allow execution of the tests with different configurations without having to use the test_config.php file, environment variables of the form PHPBB_TEST_ can now be used, e.g. PHPBB_TEST_DBMS to set the variables otherwise expected in test_config.php PHPBB3-9868 --- tests/RUNNING_TESTS.txt | 8 +++++++- tests/test_framework/phpbb_database_test_case.php | 13 ++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/RUNNING_TESTS.txt b/tests/RUNNING_TESTS.txt index a5d3111242..74a0635c1a 100644 --- a/tests/RUNNING_TESTS.txt +++ b/tests/RUNNING_TESTS.txt @@ -36,13 +36,19 @@ found on the wiki (see below). $dbuser = 'user'; $dbpasswd = 'password'; +Alternatively you can specify parameters in the environment, so e.g. the following +will run phpunit with the same parameters as in the shown test_config.php file: + + $ PHPBB_TEST_DBMS='mysqli' PHPBB_TEST_DBHOST='localhost' \ + PHPBB_TEST_DBNAME='database' PHPBB_TEST_DBUSER='user' \ + PHPBB_TEST_DBPASSWD='password' phpunit all_tests.php Running ======= Once the prerequisites are installed, run the tests from tests directory: -$ phpunit all_tests.php + $ phpunit all_tests.php More Information ================ diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index 33dbce709b..8b96298b6a 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -85,7 +85,18 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test { static $show_error = true; - if (file_exists('test_config.php')) + if (isset($_SERVER['PHPBB_TEST_DBMS'])) + { + return array( + 'dbms' => isset($_SERVER['PHPBB_TEST_DBMS']) ? $_SERVER['PHPBB_TEST_DBMS'] : '', + 'dbhost' => isset($_SERVER['PHPBB_TEST_DBHOST']) ? $_SERVER['PHPBB_TEST_DBHOST'] : '', + 'dbport' => isset($_SERVER['PHPBB_TEST_DBPORT']) ? $_SERVER['PHPBB_TEST_DBPORT'] : '', + 'dbname' => isset($_SERVER['PHPBB_TEST_DBNAME']) ? $_SERVER['PHPBB_TEST_DBNAME'] : '', + 'dbuser' => isset($_SERVER['PHPBB_TEST_DBUSER']) ? $_SERVER['PHPBB_TEST_DBUSER'] : '', + 'dbpasswd' => isset($_SERVER['PHPBB_TEST_DBPASSWD']) ? $_SERVER['PHPBB_TEST_DBPASSWD'] : '', + ); + } + else if (file_exists('test_config.php')) { include('test_config.php'); From 832035f744f8fc42f1ac491d6847dca06b9c837b Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 22 Oct 2010 20:34:52 +0200 Subject: [PATCH 4/9] [task/mssql-db-tests] Refactored getConnection into multiple smaller parts. This is a first step to simplify the extraction of database specific code parts into separate classes. PHPBB3-9868 --- .../phpbb_database_test_case.php | 161 +++++++++++------- 1 file changed, 97 insertions(+), 64 deletions(-) diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index 8b96298b6a..49121b8f8d 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -83,8 +83,6 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test public function get_database_config() { - static $show_error = true; - if (isset($_SERVER['PHPBB_TEST_DBMS'])) { return array( @@ -157,76 +155,111 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test return $data; } + /** + * Returns a PDO connection for the configured database. + * + * @param array $config The database configuration + * @param array $dbms Information on the used DBMS. + * @param bool $use_db Whether the DSN should be tied to a + * particular database making it impossible + * to delete that database. + * @return PDO The PDO database connection. + */ + public function new_pdo($config, $dbms, $delete_db) + { + $dsn = $dbms['PDO'] . ':'; + + switch ($config['dbms']) + { + case 'sqlite': + $dsn .= $config['dbhost']; + break; + + default: + $dsn .= 'host=' . $config['dbhost']; + + if ($use_db) + { + $dsn .= ';dbname=' . $config['dbname']; + } + break; + } + + $pdo = new PDO($dsn, $config['dbuser'], $config['dbpasswd']);; + + // good for debug + // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + return $pdo; + } + + private function recreate_db($config, $dbms) + { + switch ($config['dbms']) + { + case 'sqlite': + if (file_exists($config['dbhost'])) + { + unlink($config['dbhost']); + } + break; + + default: + $pdo = $this->new_pdo($config, $dbms, false); + + try + { + $pdo->exec('DROP DATABASE ' . $config['dbname']); + } + catch (PDOException $e){} // ignore non existent db + + $pdo->exec('CREATE DATABASE ' . $config['dbname']); + break; + } + } + + private function load_schema($pdo, $config, $dbms) + { + if ($config['dbms'] == 'mysql') + { + $sth = $pdo->query('SELECT VERSION() AS version'); + $row = $sth->fetch(PDO::FETCH_ASSOC); + + if (version_compare($row['version'], '4.1.3', '>=')) + { + $dbms['SCHEMA'] .= '_41'; + } + else + { + $dbms['SCHEMA'] .= '_40'; + } + } + + $sql = $this->split_sql_file(file_get_contents("../phpBB/install/schemas/{$dbms['SCHEMA']}_schema.sql"), $config['dbms']); + + foreach ($sql as $query) + { + $pdo->exec($query); + } + } + public function getConnection() { static $already_connected; - $database_config = $this->get_database_config(); + $config = $this->get_database_config(); + $dbms = $this->get_dbms_data($config['dbms']); - $dbms_data = $this->get_dbms_data($database_config['dbms']); - - if ($already_connected) + if (!$already_connected) { - if ($database_config['dbms'] == 'sqlite') - { - $pdo = new PDO($dbms_data['PDO'] . ':' . $database_config['dbhost']); - } - else - { - $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';dbname=' . $database_config['dbname'], $database_config['dbuser'], $database_config['dbpasswd']); - } + $this->recreate_db($config, $dbms); } - else + + $pdo = $this->new_pdo($config, $dbms, true); + + if (!$already_connected) { - if ($database_config['dbms'] == 'sqlite') - { - // delete existing database - if (file_exists($database_config['dbhost'])) - { - unlink($database_config['dbhost']); - } - - $pdo = new PDO($dbms_data['PDO'] . ':' . $database_config['dbhost']); - } - else - { - $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';', $database_config['dbuser'], $database_config['dbpasswd']);try - { - $pdo->exec('DROP DATABASE ' . $database_config['dbname']); - } - catch (PDOException $e){} // ignore non existent db - - $pdo->exec('CREATE DATABASE ' . $database_config['dbname']); - - $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';dbname=' . $database_config['dbname'], $database_config['dbuser'], $database_config['dbpasswd']); - } - - // good for debug - // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - if ($database_config['dbms'] == 'mysql') - { - $sth = $pdo->query('SELECT VERSION() AS version'); - $row = $sth->fetch(PDO::FETCH_ASSOC); - - if (version_compare($row['version'], '4.1.3', '>=')) - { - $dbms_data['SCHEMA'] .= '_41'; - } - else - { - $dbms_data['SCHEMA'] .= '_40'; - } - - unset($row, $sth); - } - - $sql_query = $this->split_sql_file(file_get_contents("../phpBB/install/schemas/{$dbms_data['SCHEMA']}_schema.sql"), $database_config['dbms']); - - foreach ($sql_query as $sql) - { - $pdo->exec($sql); - } + $this->load_schema($pdo, $config, $dbms); $already_connected = true; } From 801f66b4a2b6caae7b818a1aecb1c70d6ae155bb Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 22 Oct 2010 21:00:15 +0200 Subject: [PATCH 5/9] [task/mssql-db-tests] Add support for odbc & sqlsrv PDO test connections PHPBB3-9868 --- .../phpbb_database_test_case.php | 100 ++++++++++++++++-- 1 file changed, 94 insertions(+), 6 deletions(-) diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index 49121b8f8d..de9a91fa45 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -52,7 +52,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test 'mssqlnative' => array( 'SCHEMA' => 'mssql', 'DELIM' => 'GO', - 'PDO' => 'odbc', + 'PDO' => 'sqlsrv', ), 'oracle' => array( 'SCHEMA' => 'oracle', @@ -145,7 +145,8 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test if ($dbms == 'sqlite') { - // trim # off query to satisfy sqlite + // remove comment lines starting with # - they are not proper sqlite + // syntax and break sqlite2 foreach ($data as $i => $query) { $data[$i] = preg_replace('/^#.*$/m', "\n", $query); @@ -155,6 +156,66 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test return $data; } + /** + * Retrieves a list of all tables from the database. + * + * @param PDO $pdo + * @param string $dbms + * @return array(string) + */ + function get_tables($pdo, $dbms) + { + switch ($pdo) + { + case 'mysql': + case 'mysql4': + case 'mysqli': + $sql = 'SHOW TABLES'; + break; + + case 'sqlite': + $sql = 'SELECT name + FROM sqlite_master + WHERE type = "table"'; + break; + + case 'mssql': + case 'mssql_odbc': + case 'mssqlnative': + $sql = "SELECT name + FROM sysobjects + WHERE type='U'"; + break; + + case 'postgres': + $sql = 'SELECT relname + FROM pg_stat_user_tables'; + break; + + case 'firebird': + $sql = 'SELECT rdb$relation_name + FROM rdb$relations + WHERE rdb$view_source is null + AND rdb$system_flag = 0'; + break; + + case 'oracle': + $sql = 'SELECT table_name + FROM USER_TABLES'; + break; + } + + $result = $pdo->query($sql); + + $tables = array(); + while ($row = $result->fetch(PDO::FETCH_NUM)) + { + $tables[] = current($row); + } + + return $tables; + } + /** * Returns a PDO connection for the configured database. * @@ -165,16 +226,32 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test * to delete that database. * @return PDO The PDO database connection. */ - public function new_pdo($config, $dbms, $delete_db) + public function new_pdo($config, $dbms, $use_db) { $dsn = $dbms['PDO'] . ':'; - switch ($config['dbms']) + switch ($dbms['PDO']) { - case 'sqlite': + case 'sqlite2': $dsn .= $config['dbhost']; break; + case 'sqlsrv': + // prefix the hostname (or DSN) with Server= so using just (local)\SQLExpress + // works for example, further parameters can still be appended using ;x=y + $dsn .= 'Server='; + // no break -> rest like ODBC + case 'odbc': + // for ODBC assume dbhost is a suitable DSN + // e.g. Driver={SQL Server Native Client 10.0};Server=(local)\SQLExpress; + $dsn .= $config['dbhost']; + + if ($use_db) + { + $dsn .= ';Database=' . $config['dbname']; + } + break; + default: $dsn .= 'host=' . $config['dbhost']; @@ -211,7 +288,18 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test { $pdo->exec('DROP DATABASE ' . $config['dbname']); } - catch (PDOException $e){} // ignore non existent db + catch (PDOException $e) + { + // try to delete all tables if dropping the database was not possible. + foreach ($this->get_tables() as $table) + { + try + { + $pdo->exec('DROP TABLE ' . $table); + } + catch (PDOException $e){} // ignore non-existent tables + } + } $pdo->exec('CREATE DATABASE ' . $config['dbname']); break; From ee0993a8a6725bbacc341f50e37710b51df4ea5c Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 25 Oct 2010 15:50:09 +0200 Subject: [PATCH 6/9] [task/mssql-db-tests] sql_query_limit must return all results when total = 0 PHPBB3-9868 --- phpBB/includes/db/mssqlnative.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php index 44d5722e4f..93a8f91613 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/mssqlnative.php @@ -347,7 +347,8 @@ class dbal_mssqlnative extends dbal { $this->query_result = false; - if ($offset === false || $offset == 0) + // total == 0 means all results - not zero results + if ($offset == 0 && $total !== 0) { if (strpos($query, "SELECT") === false) { @@ -358,13 +359,21 @@ class dbal_mssqlnative extends dbal $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query); } } - else + else if ($offset > 0) { $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query); $query = 'SELECT * FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3 - FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3 - WHERE line3 BETWEEN ' . ($offset+1) . ' AND ' . ($offset + $total); + FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3'; + + if ($total > 0) + { + $query .= ' WHERE line3 BETWEEN ' . ($offset+1) . ' AND ' . ($offset + $total); + } + else + { + $query .= ' WHERE line3 > ' . $offset; + } } $result = $this->sql_query($query, $cache_ttl); @@ -614,4 +623,4 @@ class dbal_mssqlnative extends dbal } } -?> \ No newline at end of file +?> From 9b4da986536e0bce0359d300df84fb03e265ef53 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 25 Oct 2010 16:17:29 +0200 Subject: [PATCH 7/9] [task/mssql-db-tests] PHPUnit output got stuck after unterminated ob_start. PHPBB3-9868 --- tests/template/template.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/template/template.php b/tests/template/template.php index 024d3712f7..0c2ca8a032 100644 --- a/tests/template/template.php +++ b/tests/template/template.php @@ -36,6 +36,7 @@ class phpbb_template_template_test extends phpbb_test_case // reset the error level even when an error occured // PHPUnit turns trigger_error into exceptions as well error_reporting($error_level); + ob_end_clean(); throw $exception; } From fa8dca2400f1bef5e3faa43e491a5e2c15eafe11 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 25 Oct 2010 19:20:51 +0200 Subject: [PATCH 8/9] [task/mssql-db-tests] Split up database tests into SELECT and write operations SELECT is based on the user table fixture, write (INSERT/UPDATE/DELETE) is tested using the config table fixture. PHPBB3-9868 --- tests/dbal/all_tests.php | 6 +- tests/dbal/fixtures/config.xml | 18 ++ tests/dbal/{dbal.php => select.php} | 172 +----------------- tests/dbal/write.php | 172 ++++++++++++++++++ .../phpbb_database_test_case.php | 10 +- 5 files changed, 200 insertions(+), 178 deletions(-) create mode 100644 tests/dbal/fixtures/config.xml rename tests/dbal/{dbal.php => select.php} (74%) create mode 100644 tests/dbal/write.php diff --git a/tests/dbal/all_tests.php b/tests/dbal/all_tests.php index 7aee0f6b16..cfa8176246 100644 --- a/tests/dbal/all_tests.php +++ b/tests/dbal/all_tests.php @@ -15,7 +15,8 @@ if (!defined('PHPUnit_MAIN_METHOD')) require_once 'test_framework/framework.php'; require_once 'PHPUnit/TextUI/TestRunner.php'; -require_once 'dbal/dbal.php'; +require_once 'dbal/select.php'; +require_once 'dbal/write.php'; class phpbb_dbal_all_tests { @@ -28,7 +29,8 @@ class phpbb_dbal_all_tests { $suite = new PHPUnit_Framework_TestSuite('phpBB Database Abstraction Layer'); - $suite->addTestSuite('phpbb_dbal_test'); + $suite->addTestSuite('phpbb_dbal_select_test'); + $suite->addTestSuite('phpbb_dbal_write_test'); return $suite; } diff --git a/tests/dbal/fixtures/config.xml b/tests/dbal/fixtures/config.xml new file mode 100644 index 0000000000..019f582a91 --- /dev/null +++ b/tests/dbal/fixtures/config.xml @@ -0,0 +1,18 @@ + + + + config_name + config_value + is_dynamic + + config1 + foo + 0 + + + config2 + bar + 1 + +
+
diff --git a/tests/dbal/dbal.php b/tests/dbal/select.php similarity index 74% rename from tests/dbal/dbal.php rename to tests/dbal/select.php index 663323ad61..70f27549d2 100644 --- a/tests/dbal/dbal.php +++ b/tests/dbal/select.php @@ -10,7 +10,7 @@ require_once 'test_framework/framework.php'; require_once '../phpBB/includes/functions.php'; -class phpbb_dbal_test extends phpbb_database_test_case +class phpbb_dbal_select_test extends phpbb_database_test_case { public function getDataSet() { @@ -318,174 +318,4 @@ class phpbb_dbal_test extends phpbb_database_test_case $db->sql_freeresult($result); } - - public static function build_array_insert_data() - { - return array( - array(array( - 'config_name' => 'test_version', - 'config_value' => '0.0.0', - 'is_dynamic' => 1, - )), - array(array( - 'config_name' => 'second config', - 'config_value' => '10', - 'is_dynamic' => 0, - )), - ); - } - - /** - * @dataProvider build_array_insert_data - */ - public function test_build_array_insert($sql_ary) - { - $db = $this->new_dbal(); - - $sql = 'INSERT INTO phpbb_config ' . $db->sql_build_array('INSERT', $sql_ary); - $result = $db->sql_query($sql); - - $sql = "SELECT * - FROM phpbb_config - WHERE config_name = '" . $sql_ary['config_name'] . "'"; - $result = $db->sql_query_limit($sql, 1); - - $this->assertEquals($sql_ary, $db->sql_fetchrow($result)); - - $db->sql_freeresult($result); - } - - public static function delete_data() - { - return array( - array( - "WHERE config_name = 'test_version'", - array( - array( - 'config_name' => 'second config', - 'config_value' => '10', - 'is_dynamic' => 0, - ), - ), - ), - array( - '', - array(), - ), - ); - } - - /** - * @dataProvider delete_data - */ - public function test_delete($where, $expected) - { - $db = $this->new_dbal(); - - $sql = 'DELETE FROM phpbb_config - ' . $where; - $result = $db->sql_query($sql); - - $sql = 'SELECT * - FROM phpbb_config'; - $result = $db->sql_query($sql); - - $this->assertEquals($expected, $db->sql_fetchrowset($result)); - - $db->sql_freeresult($result); - } - - public function test_multiple_insert() - { - $db = $this->new_dbal(); - - $batch_ary = array( - array( - 'config_name' => 'batch one', - 'config_value' => 'b1', - 'is_dynamic' => 0, - ), - array( - 'config_name' => 'batch two', - 'config_value' => 'b2', - 'is_dynamic' => 1, - ), - ); - - $result = $db->sql_multi_insert('phpbb_config', $batch_ary); - - $sql = 'SELECT * - FROM phpbb_config - ORDER BY config_name ASC'; - $result = $db->sql_query($sql); - - $this->assertEquals($batch_ary, $db->sql_fetchrowset($result)); - - $db->sql_freeresult($result); - } - - public static function update_data() - { - return array( - array( - array( - 'config_value' => '20', - 'is_dynamic' => 0, - ), - " WHERE config_name = 'batch one'", - array( - array( - 'config_name' => 'batch one', - 'config_value' => '20', - 'is_dynamic' => 0, - ), - array( - 'config_name' => 'batch two', - 'config_value' => 'b2', - 'is_dynamic' => 1, - ), - ), - ), - array( - array( - 'config_value' => '0', - 'is_dynamic' => 1, - ), - '', - array( - array( - 'config_name' => 'batch one', - 'config_value' => '0', - 'is_dynamic' => 1, - ), - array( - 'config_name' => 'batch two', - 'config_value' => '0', - 'is_dynamic' => 1, - ), - ), - ), - ); - } - - /** - * @dataProvider update_data - */ - public function test_update($sql_ary, $where, $expected) - { - $db = $this->new_dbal(); - - $sql = 'UPDATE phpbb_config - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . $where; - $result = $db->sql_query($sql); - - $sql = 'SELECT * - FROM phpbb_config - ORDER BY config_name ASC'; - $result = $db->sql_query($sql); - - $this->assertEquals($expected, $db->sql_fetchrowset($result)); - - $db->sql_freeresult($result); - } } diff --git a/tests/dbal/write.php b/tests/dbal/write.php new file mode 100644 index 0000000000..01deacda69 --- /dev/null +++ b/tests/dbal/write.php @@ -0,0 +1,172 @@ +createXMLDataSet(dirname(__FILE__).'/fixtures/config.xml'); + } + + public static function build_array_insert_data() + { + return array( + array(array( + 'config_name' => 'test_version', + 'config_value' => '0.0.0', + 'is_dynamic' => 1, + )), + array(array( + 'config_name' => 'second config', + 'config_value' => '10', + 'is_dynamic' => 0, + )), + ); + } + + /** + * @dataProvider build_array_insert_data + */ + public function test_build_array_insert($sql_ary) + { + $db = $this->new_dbal(); + + $sql = 'INSERT INTO phpbb_config ' . $db->sql_build_array('INSERT', $sql_ary); + $result = $db->sql_query($sql); + + $sql = "SELECT * + FROM phpbb_config + WHERE config_name = '" . $sql_ary['config_name'] . "'"; + $result = $db->sql_query_limit($sql, 1); + + $this->assertEquals($sql_ary, $db->sql_fetchrow($result)); + + $db->sql_freeresult($result); + } + + public function test_delete() + { + $db = $this->new_dbal(); + + $sql = "DELETE FROM phpbb_config + WHERE config_name = 'config1'"; + $result = $db->sql_query($sql); + + $sql = 'SELECT * + FROM phpbb_config'; + $result = $db->sql_query($sql); + $rows = $db->sql_fetchrowset($result); + + $this->assertEquals(1, sizeof($rows)); + $this->assertEquals('config2', $rows[0]['config_name']); + + $db->sql_freeresult($result); + } + + public function test_multiple_insert() + { + $db = $this->new_dbal(); + + // empty the table + $sql = 'DELETE FROM phpbb_config'; + $db->sql_query($sql); + + $batch_ary = array( + array( + 'config_name' => 'batch one', + 'config_value' => 'b1', + 'is_dynamic' => 0, + ), + array( + 'config_name' => 'batch two', + 'config_value' => 'b2', + 'is_dynamic' => 1, + ), + ); + + $result = $db->sql_multi_insert('phpbb_config', $batch_ary); + + $sql = 'SELECT * + FROM phpbb_config + ORDER BY config_name ASC'; + $result = $db->sql_query($sql); + + $this->assertEquals($batch_ary, $db->sql_fetchrowset($result)); + + $db->sql_freeresult($result); + } + + public static function update_data() + { + return array( + array( + array( + 'config_value' => '23', + 'is_dynamic' => 0, + ), + " WHERE config_name = 'config1'", + array( + array( + 'config_name' => 'config1', + 'config_value' => '23', + 'is_dynamic' => 0, + ), + array( + 'config_name' => 'config2', + 'config_value' => 'bar', + 'is_dynamic' => 1, + ), + ), + ), + array( + array( + 'config_value' => '0', + 'is_dynamic' => 1, + ), + '', + array( + array( + 'config_name' => 'config1', + 'config_value' => '0', + 'is_dynamic' => 1, + ), + array( + 'config_name' => 'config2', + 'config_value' => '0', + 'is_dynamic' => 1, + ), + ), + ), + ); + } + + /** + * @dataProvider update_data + */ + public function test_update($sql_ary, $where, $expected) + { + $db = $this->new_dbal(); + + $sql = 'UPDATE phpbb_config + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . $where; + $result = $db->sql_query($sql); + + $sql = 'SELECT * + FROM phpbb_config + ORDER BY config_name ASC'; + $result = $db->sql_query($sql); + + $this->assertEquals($expected, $db->sql_fetchrowset($result)); + + $db->sql_freeresult($result); + } +} diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index de9a91fa45..a64bae8c57 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -9,6 +9,8 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_TestCase { + private static $already_connected; + protected $test_case_helpers; public function get_test_case_helpers() @@ -333,23 +335,21 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test public function getConnection() { - static $already_connected; - $config = $this->get_database_config(); $dbms = $this->get_dbms_data($config['dbms']); - if (!$already_connected) + if (!self::$already_connected) { $this->recreate_db($config, $dbms); } $pdo = $this->new_pdo($config, $dbms, true); - if (!$already_connected) + if (!self::$already_connected) { $this->load_schema($pdo, $config, $dbms); - $already_connected = true; + self::$already_connected = true; } return $this->createDefaultDBConnection($pdo, 'testdb'); From 76e8a9466ef3227337dd18faf9b623195af00364 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 25 Oct 2010 19:22:57 +0200 Subject: [PATCH 9/9] [task/mssql-db-tests] Remove MS SQL helper values from SELECT LIMIT results. PHPBB3-9868 --- phpBB/includes/db/mssqlnative.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php index 93a8f91613..1e0a8077e7 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/mssqlnative.php @@ -413,13 +413,18 @@ class dbal_mssqlnative extends dbal $row = @sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC); - // I hope i am able to remove this later... hopefully only a PHP or MSSQL bug if ($row) { foreach ($row as $key => $value) { $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; } + + // remove helper values from LIMIT queries + if (isset($row['line2'])) + { + unset($row['line2'], $row['line3']); + } } return $row; }