diff options
| -rw-r--r-- | tests/RUNNING_TESTS.txt | 21 | ||||
| -rw-r--r-- | tests/test_framework/phpbb_database_connection_odbc_pdo_wrapper.php | 37 | ||||
| -rw-r--r-- | tests/test_framework/phpbb_database_test_case.php | 35 | ||||
| -rw-r--r-- | tests/test_framework/phpbb_database_test_connection_manager.php | 110 | ||||
| -rw-r--r-- | tests/test_framework/phpbb_test_case_helpers.php | 4 | 
5 files changed, 201 insertions, 6 deletions
diff --git a/tests/RUNNING_TESTS.txt b/tests/RUNNING_TESTS.txt index b976545c22..7c2a7c3fce 100644 --- a/tests/RUNNING_TESTS.txt +++ b/tests/RUNNING_TESTS.txt @@ -51,6 +51,27 @@ test_config.php file:        PHPBB_TEST_DBNAME='database' PHPBB_TEST_DBUSER='user' \        PHPBB_TEST_DBPASSWD='password' phpunit +Special Database Cases +---------------------- +In order to run tests on some of the databases that we support, it will be +necessary to provide a custom DSN string in test_config.php. This is only +needed for MSSQL 2000+ (PHP module), MSSQL via ODBC, and Firebird when +PDO_Firebird does not work on your system +(https://bugs.php.net/bug.php?id=61183). The variable must be named $custom_dsn. + +Examples: +Firebird using http://www.firebirdsql.org/en/odbc-driver/ +$custom_dsn = "Driver={Firebird/InterBase(r) driver};dbname=$dbhost:$dbname"; + +MSSQL +$custom_dsn = "Driver={SQL Server Native Client 10.0};Server=$dbhost;Database=$dbname"; + +The other fields in test_config.php should be filled out as you would normally +to connect to that database in phpBB. + +Additionally, you will need to be running the DbUnit fork from +https://github.com/phpbb/dbunit/tree/phpbb. +  Running  ======= diff --git a/tests/test_framework/phpbb_database_connection_odbc_pdo_wrapper.php b/tests/test_framework/phpbb_database_connection_odbc_pdo_wrapper.php new file mode 100644 index 0000000000..ec59fa3886 --- /dev/null +++ b/tests/test_framework/phpbb_database_connection_odbc_pdo_wrapper.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +if (!class_exists('PDO')) +{ +	return; +} + +/** +* Used for passing in information about the PDO driver +* since the PDO class reveals nothing about the DSN that +* the user provided. +* +* This is used in the custom PHPUnit ODBC driver +*/ +class phpbb_database_connection_odbc_pdo_wrapper extends PDO +{ +	// Name of the driver being used (i.e. mssql, firebird) +	public $driver = ''; + +	// Version number of driver since PDO::getAttribute(PDO::ATTR_CLIENT_VERSION) is pretty useless for this +	public $version = 0; + +	function __construct($dbms, $version, $dsn, $user, $pass) +	{ +		$this->driver = $dbms; +		$this->version = (double) $version; + +		parent::__construct($dsn, $user, $pass); +	} +} diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index e742b543b0..bb86df0ef0 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -28,6 +28,28 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test  		);  	} +	public function createXMLDataSet($path) +	{ +		$db_config = $this->get_database_config(); + +		// Firebird requires table and column names to be uppercase +		if ($db_config['dbms'] == 'firebird') +		{ +			$xml_data = file_get_contents($path); +			$xml_data = preg_replace_callback('/(?:(<table name="))([a-z_]+)(?:(">))/', 'phpbb_database_test_case::to_upper', $xml_data); +			$xml_data = preg_replace_callback('/(?:(<column>))([a-z_]+)(?:(<\/column>))/', 'phpbb_database_test_case::to_upper', $xml_data); + +			$new_fixture = tmpfile(); +			fwrite($new_fixture, $xml_data); +			fseek($new_fixture, 0); + +			$meta_data = stream_get_meta_data($new_fixture); +			$path = $meta_data['uri']; +		} + +		return parent::createXMLDataSet($path); +	} +  	public function get_test_case_helpers()  	{  		if (!$this->test_case_helpers) @@ -106,4 +128,17 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test  	{  		return new phpbb_database_test_connection_manager($config);  	} + +	/** +	* Converts a match in the middle of a string to uppercase. +	* This is necessary for transforming the fixture information for Firebird tests +	* +	* @param $matches The array of matches from a regular expression +	* +	* @return string The string with the specified match converted to uppercase +	*/ +	public static function to_upper($matches) +	{ +		return $matches[1] . strtoupper($matches[2]) . $matches[3]; +	}  } diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php index dacbbe2dc4..25e0972f42 100644 --- a/tests/test_framework/phpbb_database_test_connection_manager.php +++ b/tests/test_framework/phpbb_database_test_connection_manager.php @@ -8,6 +8,7 @@  */  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_install.php'; +require_once dirname(__FILE__) . '/phpbb_database_connection_odbc_pdo_wrapper.php';  class phpbb_database_test_connection_manager  { @@ -62,6 +63,13 @@ class phpbb_database_test_connection_manager  				// e.g. Driver={SQL Server Native Client 10.0};Server=(local)\SQLExpress;  				$dsn .= $this->config['dbhost']; +				// Primarily for MSSQL Native/Azure as ODBC needs it in $dbhost, attached to the Server param +				if ($this->config['dbport']) +				{ +					$port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; +					$dsn .= $port_delimiter . $this->config['dbport']; +				} +  				if ($use_db)  				{  					$dsn .= ';Database=' . $this->config['dbname']; @@ -98,9 +106,34 @@ class phpbb_database_test_connection_manager  			break;  		} +		// These require different connection strings on the phpBB side than they do in PDO +		// so you must provide a DSN string for ODBC separately +		if (!empty($this->config['custom_dsn']) && ($this->config['dbms'] == 'mssql' || $this->config['dbms'] == 'firebird')) +		{ +			$dsn = 'odbc:' . $this->config['custom_dsn']; +		} +  		try  		{ -			$this->pdo = new PDO($dsn, $this->config['dbuser'], $this->config['dbpasswd']); +			switch ($this->config['dbms']) +			{ +				case 'mssql': +				case 'mssql_odbc': +					$this->pdo = new phpbb_database_connection_odbc_pdo_wrapper('mssql', 0, $dsn, $this->config['dbuser'], $this->config['dbpasswd']); +				break; + +				case 'firebird': +					if (!empty($this->config['custom_dsn'])) +					{ +						$this->pdo = new phpbb_database_connection_odbc_pdo_wrapper('firebird', 0, $dsn, $this->config['dbuser'], $this->config['dbpasswd']); +						break; +					} +					// Fall through if they're using the firebird PDO driver and not the generic ODBC driver + +				default: +					$this->pdo = new PDO($dsn, $this->config['dbuser'], $this->config['dbpasswd']); +				break; +			}  		}  		catch (PDOException $e)  		{ @@ -108,8 +141,7 @@ class phpbb_database_test_connection_manager  			throw new Exception("Unable do connect to $cleaned_dsn using PDO with error: {$e->getMessage()}");  		} -		// good for debug -		// $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +		$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  	}  	/** @@ -140,12 +172,41 @@ class phpbb_database_test_connection_manager  				}  			break; +			case 'firebird': +				$this->connect(); +				// Drop all of the tables +				foreach ($this->get_tables() as $table) +				{ +					$this->pdo->exec('DROP TABLE ' . $table); +				} +				$this->purge_extras(); +			break; + +			case 'oracle': +				$this->connect(); +				// Drop all of the tables +				foreach ($this->get_tables() as $table) +				{ +					$this->pdo->exec('DROP TABLE ' . $table . ' CASCADE CONSTRAINTS'); +				} +				$this->purge_extras(); +			break; +  			default:  				$this->connect(false);  				try  				{  					$this->pdo->exec('DROP DATABASE ' . $this->config['dbname']); + +					try +					{ +						$this->pdo->exec('CREATE DATABASE ' . $this->config['dbname']); +					} +					catch (PDOException $e) +					{ +						throw new Exception("Unable to re-create database: {$e->getMessage()}"); +					}  				}  				catch (PDOException $e)  				{ @@ -154,9 +215,8 @@ class phpbb_database_test_connection_manager  					{  						$this->pdo->exec('DROP TABLE ' . $table);  					} +					$this->purge_extras();  				} - -				$this->pdo->exec('CREATE DATABASE ' . $this->config['dbname']);  			 break;  		}  	} @@ -332,4 +392,44 @@ class phpbb_database_test_connection_manager  			throw new Exception($message);  		}  	} + +	/** +	* Removes extra objects from a database. This is for cases where dropping the database fails. +	*/ +	public function purge_extras() +	{ +		$this->ensure_connected(__METHOD__); +		$queries = array(); + +		switch ($this->config['dbms']) +		{ +			case 'firebird': +				$sql = 'SELECT RDB$GENERATOR_NAME +					FROM RDB$GENERATORS +					WHERE RDB$SYSTEM_FLAG = 0'; +				$result = $this->pdo->query($sql); + +				while ($row = $result->fetch(PDO::FETCH_NUM)) +				{ +					$queries[] = 'DROP GENERATOR ' . current($row); +				} +			break; + +			case 'oracle': +				$sql = 'SELECT sequence_name +					FROM USER_SEQUENCES'; +				$result = $this->pdo->query($sql); + +				while ($row = $result->fetch(PDO::FETCH_NUM)) +				{ +					$queries[] = 'DROP SEQUENCE ' . current($row); +				} +			break; +		} + +		foreach ($queries as $query) +		{ +			$this->pdo->exec($query); +		} +	}  } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 2a3c27f9f9..29adfc6817 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -79,6 +79,7 @@ class phpbb_test_case_helpers  				'dbname'	=> $dbname,  				'dbuser'	=> $dbuser,  				'dbpasswd'	=> $dbpasswd, +				'custom_dsn'	=> isset($custom_dsn) ? $custom_dsn : '',  			));  			if (isset($phpbb_functional_url)) @@ -95,7 +96,8 @@ class phpbb_test_case_helpers  				'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'] : '' +				'dbpasswd'	=> isset($_SERVER['PHPBB_TEST_DBPASSWD']) ? $_SERVER['PHPBB_TEST_DBPASSWD'] : '', +				'custom_dsn'	=> isset($_SERVER['PHPBB_TEST_CUSTOM_DSN']) ? $_SERVER['PHPBB_TEST_CUSTOM_DSN'] : '',  			));  		}  | 
