diff options
Diffstat (limited to 'tests')
53 files changed, 2240 insertions, 173 deletions
diff --git a/tests/RUNNING_TESTS.txt b/tests/RUNNING_TESTS.txt index 59197acc0f..de9c751238 100644 --- a/tests/RUNNING_TESTS.txt +++ b/tests/RUNNING_TESTS.txt @@ -17,16 +17,34 @@ 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 +- ctype (also a PHPUnit dependency) +- dom (PHPUnit dependency) + +Some of the functionality in phpBB and/or the test suite uses additional +PHP extensions. If these extensions are not loaded, respective tests +will be skipped: + +- apc (APC cache driver) +- bz2 (compress tests) +- interbase, pdo_firebird (Firebird database driver) +- mysql, pdo_mysql (MySQL database driver) +- mysqli, pdo_mysql (MySQLi database driver) +- pdo (any database tests) +- pgsql, pdo_pgsql (PostgreSQL database driver) +- simplexml (any database tests) +- sqlite, pdo_sqlite (SQLite database driver, requires SQLite 2.x support + in pdo_sqlite) +- zlib (compress tests) 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). +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). <?php $dbms = 'mysqli'; @@ -36,26 +54,56 @@ 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: +It is possible to have multiple test_config.php files, for example if you +are testing on multiple databases. You can specify which test_config.php file +to use in the environment as follows: + + $ PHPBB_TEST_CONFIG=tests/test_config.php phpunit + +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 +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 ======= -Once the prerequisites are installed, run the tests from the project root directory (above phpBB): +Once the prerequisites are installed, run the tests from the project root +directory (above phpBB): $ phpunit Slow tests -------------- + Certain tests, such as the UTF-8 normalizer or the DNS tests tend to be slow. Thus these tests are in the `slow` group, which is excluded by default. You can -enable slow tests by copying the phpunit.xml.all file to phpunit.xml. If you only -want the slow tests, run: +enable slow tests by copying the phpunit.xml.all file to phpunit.xml. If you +only want the slow tests, run: $ phpunit --group slow @@ -63,4 +111,4 @@ More Information ================ Further information is available on phpbb wiki: -http://wiki.phpbb.com/display/DEV/Unit+Tests +http://wiki.phpbb.com/Unit_Tests diff --git a/tests/bbcode/url_bbcode_test.php b/tests/bbcode/url_bbcode_test.php index 15bdfc434f..6b5afe5808 100644 --- a/tests/bbcode/url_bbcode_test.php +++ b/tests/bbcode/url_bbcode_test.php @@ -11,7 +11,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/bbcode.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/message_parser.php'; -require_once dirname(__FILE__) . '/../mock_user.php'; +require_once dirname(__FILE__) . '/../mock/user.php'; class phpbb_url_bbcode_test extends phpbb_test_case { diff --git a/tests/bootstrap.php b/tests/bootstrap.php index d6c5d25bc8..d687db622a 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -22,5 +22,20 @@ require_once 'test_framework/phpbb_database_test_connection_manager.php'; if (version_compare(PHP_VERSION, '5.3.0-dev', '>=')) { + if (getenv('PHPBB_NO_COMPOSER_AUTOLOAD')) + { + if (getenv('PHPBB_AUTOLOAD')) + { + require(getenv('PHPBB_AUTOLOAD')); + } + } + else + { + if (!file_exists($phpbb_root_path . 'vendor/autoload.php')) + { + trigger_error('You have not set up composer dependencies. See http://getcomposer.org/.', E_USER_ERROR); + } + require($phpbb_root_path . 'vendor/autoload.php'); + } require_once 'test_framework/phpbb_functional_test_case.php'; } diff --git a/tests/compress/archive/.gitkeep b/tests/compress/archive/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/compress/archive/.gitkeep diff --git a/tests/compress/compress_test.php b/tests/compress/compress_test.php new file mode 100644 index 0000000000..ce193cf3ba --- /dev/null +++ b/tests/compress/compress_test.php @@ -0,0 +1,173 @@ +<?php +/** + * + * @package testing + * @copyright (c) 2012 phpBB Group + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 + * + */ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compress.php'; + +class phpbb_compress_test extends phpbb_test_case +{ + const EXTRACT_DIR = '/extract/'; + const ARCHIVE_DIR = '/archive/'; + + private $path; + + protected $filelist = array( + '1.txt', + 'dir/2.txt', + 'dir/3.txt', + 'dir/subdir/4.txt', + ); + + protected function setUp() + { + // Required for compress::add_file + global $phpbb_root_path; + $phpbb_root_path = ''; + + $this->path = dirname(__FILE__) . '/fixtures/'; + } + + protected function check_extensions($extensions) + { + foreach ($extensions as $extension) + { + if (!@extension_loaded($extension)) + { + $this->markTestSkipped("$extension extension is not loaded"); + } + } + } + + protected function tearDown() + { + foreach (array(dirname(__FILE__) . self::EXTRACT_DIR, dirname(__FILE__) . self::ARCHIVE_DIR) as $dir) + { + $this->clear_dir($dir); + } + } + + protected function clear_dir($dir) + { + $iterator = new DirectoryIterator($dir); + foreach ($iterator as $fileinfo) + { + $name = $fileinfo->getFilename(); + $path = $fileinfo->getPathname(); + + if ($name[0] !== '.') + { + if ($fileinfo->isDir()) + { + $this->clear_dir($path); + rmdir($path); + } + else + { + unlink($path); + } + } + } + } + + protected function archive_files($compress) + { + $compress->add_file($this->path . '1.txt', $this->path); + $compress->add_file( + 'tests/compress/fixtures/dir/', + 'tests/compress/fixtures/', + '', + // The comma here is not an error, this is a comma-separated list + 'subdir/4.txt,3.txt' + ); + $compress->add_custom_file($this->path . 'dir/3.txt', 'dir/3.txt'); + $compress->add_data(file_get_contents($this->path . 'dir/subdir/4.txt'), 'dir/subdir/4.txt'); + } + + protected function valid_extraction($extra = array()) + { + $filelist = array_merge($this->filelist, $extra); + + foreach ($filelist as $filename) + { + $path = dirname(__FILE__) . self::EXTRACT_DIR . $filename; + $this->assertTrue(file_exists($path)); + + // Check the file's contents is correct + $contents = explode('_', basename($filename, '.txt')); + $contents = $contents[0]; + $this->assertEquals($contents . "\n", file_get_contents($path)); + } + } + + public function tar_archive_list() + { + return array( + array('archive.tar', '.tar', array()), + array('archive.tar.gz', '.tar.gz', array('zlib')), + array('archive.tar.bz2', '.tar.bz2', array('bz2')), + ); + } + + /** + * @dataProvider tar_archive_list + */ + public function test_extract_tar($filename, $type, $extensions) + { + $this->check_extensions($extensions); + $compress = new compress_tar('r', $this->path . $filename); + $compress->extract('tests/compress/' . self::EXTRACT_DIR); + $this->valid_extraction(); + } + + public function test_extract_zip() + { + $compress = new compress_zip('r', $this->path . 'archive.zip'); + $compress->extract('tests/compress/' . self::EXTRACT_DIR); + $this->valid_extraction(); + } + + /** + * @depends test_extract_tar + * @dataProvider tar_archive_list + */ + public function test_compress_tar($filename, $type, $extensions) + { + $this->check_extensions($extensions); + + $tar = dirname(__FILE__) . self::ARCHIVE_DIR . $filename; + $compress = new compress_tar('w', $tar); + $this->archive_files($compress); + $compress->close(); + $this->assertTrue(file_exists($tar)); + + $compress->mode = 'r'; + $compress->open(); + $compress->extract('tests/compress/' . self::EXTRACT_DIR); + $this->valid_extraction(); + } + + /** + * @depends test_extract_zip + */ + public function test_compress_zip() + { + $this->check_extensions(array('zlib')); + + $zip = dirname(__FILE__) . self::ARCHIVE_DIR . 'archive.zip'; + $compress = new compress_zip('w', $zip); + $this->archive_files($compress); + $compress->close(); + $this->assertTrue(file_exists($zip)); + + $compress = new compress_zip('r', $zip); + $compress->extract('tests/compress/' . self::EXTRACT_DIR); + $this->valid_extraction(); + } +} diff --git a/tests/compress/extract/.gitkeep b/tests/compress/extract/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/compress/extract/.gitkeep diff --git a/tests/compress/fixtures/1.txt b/tests/compress/fixtures/1.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/compress/fixtures/1.txt @@ -0,0 +1 @@ +1 diff --git a/tests/compress/fixtures/archive.tar b/tests/compress/fixtures/archive.tar Binary files differnew file mode 100644 index 0000000000..54ed56084e --- /dev/null +++ b/tests/compress/fixtures/archive.tar diff --git a/tests/compress/fixtures/archive.tar.bz2 b/tests/compress/fixtures/archive.tar.bz2 Binary files differnew file mode 100644 index 0000000000..04c0eccd74 --- /dev/null +++ b/tests/compress/fixtures/archive.tar.bz2 diff --git a/tests/compress/fixtures/archive.tar.gz b/tests/compress/fixtures/archive.tar.gz Binary files differnew file mode 100644 index 0000000000..195e7a060a --- /dev/null +++ b/tests/compress/fixtures/archive.tar.gz diff --git a/tests/compress/fixtures/archive.zip b/tests/compress/fixtures/archive.zip Binary files differnew file mode 100644 index 0000000000..bdb618fc26 --- /dev/null +++ b/tests/compress/fixtures/archive.zip diff --git a/tests/compress/fixtures/dir/2.txt b/tests/compress/fixtures/dir/2.txt new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/tests/compress/fixtures/dir/2.txt @@ -0,0 +1 @@ +2 diff --git a/tests/compress/fixtures/dir/3.txt b/tests/compress/fixtures/dir/3.txt new file mode 100644 index 0000000000..00750edc07 --- /dev/null +++ b/tests/compress/fixtures/dir/3.txt @@ -0,0 +1 @@ +3 diff --git a/tests/compress/fixtures/dir/subdir/4.txt b/tests/compress/fixtures/dir/subdir/4.txt new file mode 100644 index 0000000000..b8626c4cff --- /dev/null +++ b/tests/compress/fixtures/dir/subdir/4.txt @@ -0,0 +1 @@ +4 diff --git a/tests/dbal/auto_increment_test.php b/tests/dbal/auto_increment_test.php new file mode 100644 index 0000000000..e87fc1c6bd --- /dev/null +++ b/tests/dbal/auto_increment_test.php @@ -0,0 +1,100 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/db/db_tools.php'; + +class phpbb_dbal_auto_increment_test extends phpbb_database_test_case +{ + protected $db; + protected $tools; + protected $table_exists; + protected $table_data; + + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml'); + } + + protected function setUp() + { + parent::setUp(); + + $this->db = $this->new_dbal(); + $this->tools = new phpbb_db_tools($this->db); + + $this->table_data = array( + 'COLUMNS' => array( + 'c_id' => array('UINT', NULL, 'auto_increment'), + 'c_uint' => array('UINT', 4), + ), + 'PRIMARY_KEY' => 'c_id', + ); + $this->tools->sql_create_table('prefix_table_name', $this->table_data); + $this->table_exists = true; + } + + protected function tearDown() + { + if ($this->table_exists) + { + $this->tools->sql_table_drop('prefix_table_name'); + } + + parent::tearDown(); + } + + static protected function get_default_values() + { + return array( + 'c_uint' => 0, + ); + } + + public function test_auto_increment() + { + $sql = 'DELETE FROM prefix_table_name'; + $result = $this->db->sql_query($sql); + + $row1 = array_merge(self::get_default_values(), array( + 'c_uint' => 1, + )); + $row2 = array_merge(self::get_default_values(), array( + 'c_uint' => 2, + )); + + $sql = 'INSERT INTO prefix_table_name ' . $this->db->sql_build_array('INSERT', $row1); + $result = $this->db->sql_query($sql); + $id1 = $this->db->sql_nextid(); + + $sql = 'INSERT INTO prefix_table_name ' . $this->db->sql_build_array('INSERT', $row2); + $result = $this->db->sql_query($sql); + $id2 = $this->db->sql_nextid(); + + $this->assertGreaterThan($id1, $id2, 'Auto increment should increase the id value'); + + $sql = "SELECT * + FROM prefix_table_name WHERE c_id = $id1"; + $result = $this->db->sql_query($sql); + $row_actual = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $row1['c_id'] = $id1; + $this->assertEquals($row1, $row_actual); + + $sql = "SELECT * + FROM prefix_table_name WHERE c_id = $id2"; + $result = $this->db->sql_query($sql); + $row_actual = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + $row2['c_id'] = $id2; + $this->assertEquals($row2, $row_actual); + } +} diff --git a/tests/dbal/connect_test.php b/tests/dbal/connect_test.php new file mode 100644 index 0000000000..505ce28fa1 --- /dev/null +++ b/tests/dbal/connect_test.php @@ -0,0 +1,43 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_dbal_connect_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__) . '/../fixtures/empty.xml'); + } + + public function test_failing_connect() + { + global $phpbb_root_path, $phpEx; + + $config = $this->get_database_config(); + + require_once dirname(__FILE__) . '/../../phpBB/includes/db/' . $config['dbms'] . '.php'; + $dbal = 'dbal_' . $config['dbms']; + $db = new $dbal(); + + // Failure to connect results in a trigger_error call in dbal. + // phpunit converts triggered errors to exceptions. + // In particular there should be no fatals here. + try + { + $db->sql_connect($config['dbhost'], 'phpbbogus', 'phpbbogus', 'phpbbogus', $config['dbport']); + $this->assertFalse(true); + } + catch (Exception $e) + { + // should have a legitimate message + $this->assertNotEmpty($e->getMessage()); + } + } +} diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index c7ddb88ce8..c20e46011f 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -106,7 +106,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case 'c_bool' => 0, 'c_vchar' => '', 'c_vchar_size' => '', - 'c_char_size' => '', + 'c_char_size' => 'abcd', 'c_xstext' => '', 'c_stext' => '', 'c_text' => '', @@ -165,6 +165,11 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case */ public function test_created_column($column_name, $column_value) { + if ($column_name === 'c_varbinary' && stripos(get_class($this->db), 'mysql') === false) + { + $this->markTestIncomplete('Binary handling is not implemented properly on non-MySQL DBMSes.'); + } + $row_insert = self::get_default_values(); $row_insert[$column_name] = $column_value; @@ -189,51 +194,6 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case $this->assertEquals($row_expect[$column_name], $row_actual[$column_name], "Column $column_name of type $type should have equal return and input value."); } - public function test_auto_increment() - { - $sql = 'DELETE FROM prefix_table_name'; - $result = $this->db->sql_query($sql); - - $row1 = array_merge(self::get_default_values(), array( - 'c_uint' => 1, - 'c_vchar' => '1', // these values are necessary to avoid unique index issues - 'c_vchar_size' => '1', - )); - $row2 = array_merge(self::get_default_values(), array( - 'c_uint' => 2, - 'c_vchar' => '2', - 'c_vchar_size' => '2', - )); - - $sql = 'INSERT INTO prefix_table_name ' . $this->db->sql_build_array('INSERT', $row1); - $result = $this->db->sql_query($sql); - $id1 = $this->db->sql_nextid(); - - $sql = 'INSERT INTO prefix_table_name ' . $this->db->sql_build_array('INSERT', $row2); - $result = $this->db->sql_query($sql); - $id2 = $this->db->sql_nextid(); - - $this->assertGreaterThan($id1, $id2, 'Auto increment should increase the id value'); - - $sql = "SELECT * - FROM prefix_table_name WHERE c_id = $id1"; - $result = $this->db->sql_query($sql); - $row_actual = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $row1['c_id'] = $id1; - $this->assertEquals($row1, $row_actual); - - $sql = "SELECT * - FROM prefix_table_name WHERE c_id = $id2"; - $result = $this->db->sql_query($sql); - $row_actual = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $row2['c_id'] = $id2; - $this->assertEquals($row2, $row_actual); - } - public function test_list_columns() { $this->assertEquals( diff --git a/tests/dbal/select_test.php b/tests/dbal/select_test.php index 21b12777dc..6dbab05a41 100644 --- a/tests/dbal/select_test.php +++ b/tests/dbal/select_test.php @@ -17,7 +17,7 @@ class phpbb_dbal_select_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/three_users.xml'); } - public static function return_on_error_select_data() + static public function return_on_error_select_data() { return array( array('phpbb_users', "username_clean = 'bertie'", array(array('username_clean' => 'bertie'))), @@ -44,7 +44,7 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $this->assertEquals($expected, $db->sql_fetchrowset($result)); } - public static function fetchrow_data() + static public function fetchrow_data() { return array( array('', array(array('username_clean' => 'barfoo'), @@ -95,7 +95,7 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $db->sql_freeresult($result); } - public static function fetchfield_data() + static public function fetchfield_data() { return array( array('', array('barfoo', 'foobar', 'bertie')), @@ -125,7 +125,33 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $this->assertEquals($expected, $ary); } - public static function query_limit_data() + static public function fetchfield_seek_data() + { + return array( + array(1, 'foobar'), + array(0, 'barfoo'), + array(2, 'bertie'), + ); + } + + /** + * @dataProvider fetchfield_seek_data + */ + public function test_fetchfield_seek($rownum, $expected) + { + $db = $this->new_dbal(); + + $result = $db->sql_query('SELECT username_clean + FROM phpbb_users + ORDER BY user_id ASC'); + + $field = $db->sql_fetchfield('username_clean', $rownum, $result); + $db->sql_freeresult($result); + + $this->assertEquals($expected, $field); + } + + static public function query_limit_data() { return array( array(0, 0, array(array('username_clean' => 'barfoo'), @@ -166,7 +192,7 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $this->assertEquals($expected, $ary); } - public static function like_expression_data() + static public function like_expression_data() { // * = any_char; # = one_char return array( @@ -203,7 +229,7 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $db->sql_freeresult($result); } - public static function in_set_data() + static public function in_set_data() { return array( array('user_id', 3, false, false, array(array('username_clean' => 'bertie'))), @@ -277,7 +303,7 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $db->sql_freeresult($result); } - public static function build_array_data() + static public function build_array_data() { return array( array(array('username_clean' => 'barfoo'), array(array('username_clean' => 'barfoo'))), @@ -349,7 +375,9 @@ class phpbb_dbal_select_test extends phpbb_database_test_case { $db = $this->new_dbal(); - $sql = 'SELECT * FROM (SELECT 1) AS TBL WHERE 1 = 0'; + $sql = 'SELECT user_id + FROM phpbb_users + WHERE 1 = 0'; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); diff --git a/tests/dbal/write_sequence_test.php b/tests/dbal/write_sequence_test.php new file mode 100644 index 0000000000..8975cfbfb1 --- /dev/null +++ b/tests/dbal/write_sequence_test.php @@ -0,0 +1,55 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_dbal_write_sequence_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/three_users.xml'); + } + + static public function write_sequence_data() + { + return array( + array( + 'ticket/11219', + 4, + ), + ); + } + + /** + * @dataProvider write_sequence_data + */ + public function test_write_sequence($username, $expected) + { + $db = $this->new_dbal(); + + $sql = 'INSERT INTO phpbb_users ' . $db->sql_build_array('INSERT', array( + 'username' => $username, + 'username_clean' => $username, + 'user_permissions' => '', + 'user_sig' => '', + 'user_occ' => '', + 'user_interests' => '', + )); + $db->sql_query($sql); + + $this->assertEquals($expected, $db->sql_nextid()); + + $sql = "SELECT user_id + FROM phpbb_users + WHERE username_clean = '" . $db->sql_escape($username) . "'"; + $result = $db->sql_query_limit($sql, 1); + + $this->assertEquals($expected, $db->sql_fetchfield('user_id')); + } +} diff --git a/tests/dbal/write_test.php b/tests/dbal/write_test.php index 596c50a220..ecfd774896 100644 --- a/tests/dbal/write_test.php +++ b/tests/dbal/write_test.php @@ -16,7 +16,7 @@ class phpbb_dbal_write_test extends phpbb_database_test_case return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/config.xml'); } - public static function build_array_insert_data() + static public function build_array_insert_data() { return array( array(array( @@ -104,7 +104,7 @@ class phpbb_dbal_write_test extends phpbb_database_test_case $db->sql_freeresult($result); } - public static function update_data() + static public function update_data() { return array( array( diff --git a/tests/fixtures/empty.xml b/tests/fixtures/empty.xml new file mode 100644 index 0000000000..195e30e38d --- /dev/null +++ b/tests/fixtures/empty.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> + <table name="phpbb_sessions"> + <column>session_id</column> + <column>session_user_id</column> + <column>session_ip</column> + <column>session_browser</column> + </table> +</dataset> diff --git a/tests/functional/auth_test.php b/tests/functional/auth_test.php new file mode 100644 index 0000000000..662b1bd38b --- /dev/null +++ b/tests/functional/auth_test.php @@ -0,0 +1,52 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @group functional +*/ +class phpbb_functional_auth_test extends phpbb_functional_test_case +{ + public function test_login() + { + $this->login(); + + // check for logout link + $crawler = $this->request('GET', 'index.php'); + $this->assert_response_success(); + $this->assertContains($this->lang('LOGOUT_USER', 'admin'), $crawler->filter('.navbar')->text()); + } + + public function test_login_other() + { + $this->create_user('anothertestuser'); + $this->login('anothertestuser'); + $crawler = $this->request('GET', 'index.php'); + $this->assert_response_success(); + $this->assertContains('anothertestuser', $crawler->filter('.icon-logout')->text()); + } + + /** + * @depends test_login + */ + public function test_logout() + { + $this->login(); + $this->add_lang('ucp'); + + // logout + $crawler = $this->request('GET', 'ucp.php?sid=' . $this->sid . '&mode=logout'); + $this->assert_response_success(); + $this->assertContains($this->lang('LOGOUT_REDIRECT'), $crawler->filter('#message')->text()); + + // look for a register link, which should be visible only when logged out + $crawler = $this->request('GET', 'index.php'); + $this->assert_response_success(); + $this->assertContains($this->lang('REGISTER'), $crawler->filter('.navbar')->text()); + } +} diff --git a/tests/functional/browse_test.php b/tests/functional/browse_test.php index 723cf93232..b5748059c6 100644 --- a/tests/functional/browse_test.php +++ b/tests/functional/browse_test.php @@ -15,12 +15,21 @@ class phpbb_functional_browse_test extends phpbb_functional_test_case public function test_index() { $crawler = $this->request('GET', 'index.php'); + $this->assert_response_success(); $this->assertGreaterThan(0, $crawler->filter('.topiclist')->count()); } public function test_viewforum() { $crawler = $this->request('GET', 'viewforum.php?f=2'); + $this->assert_response_success(); $this->assertGreaterThan(0, $crawler->filter('.topiclist')->count()); } + + public function test_viewtopic() + { + $crawler = $this->request('GET', 'viewtopic.php?t=1'); + $this->assert_response_success(); + $this->assertGreaterThan(0, $crawler->filter('.postbody')->count()); + } } diff --git a/tests/functional/lang_test.php b/tests/functional/lang_test.php new file mode 100644 index 0000000000..053806a431 --- /dev/null +++ b/tests/functional/lang_test.php @@ -0,0 +1,45 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @group functional +*/ +class phpbb_functional_lang_test extends phpbb_functional_test_case +{ + public function test_lang() + { + // Test a language string present in the common language file + $this->assertEquals('Board index', $this->lang('FORUM_INDEX')); + } + + /** + * @expectedException RuntimeException + */ + public function test_lang_missing() + { + $this->assertEquals('Your account has now been activated. Thank you for registering.', $this->lang('ACCOUNT_ACTIVE')); + } + + public function test_add_lang() + { + $this->add_lang('ucp'); + + // Test a language string present only in the UCP language file + $this->assertEquals('Your account has now been activated. Thank you for registering.', $this->lang('ACCOUNT_ACTIVE')); + } + + public function test_add_langs() + { + $this->add_lang(array('groups', 'memberlist')); + + // Test a language string from each UCP and memberlist + $this->assertEquals('The selected group is already your default group.', $this->lang('ALREADY_DEFAULT_GROUP')); + $this->assertEquals('Profile', $this->lang('ABOUT_USER')); + } +} diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php new file mode 100644 index 0000000000..d05207edf0 --- /dev/null +++ b/tests/functional/posting_test.php @@ -0,0 +1,139 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @group functional +*/ +class phpbb_functional_posting_test extends phpbb_functional_test_case +{ + public function test_post_new_topic() + { + $this->login(); + + // Test creating topic + $post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.'); + + $crawler = $this->request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); + $this->assertContains('This is a test topic posted by the testing framework.', $crawler->filter('html')->text()); + + // Test creating a reply + $post2 = $this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', 'This is a test post posted by the testing framework.'); + + $crawler = $this->request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}"); + $this->assertContains('This is a test post posted by the testing framework.', $crawler->filter('html')->text()); + + // Test quoting a message + $crawler = $this->request('GET', "posting.php?mode=quote&f=2&t={$post2['topic_id']}&p={$post2['post_id']}&sid={$this->sid}"); + $this->assert_response_success(); + $this->assertContains('This is a test post posted by the testing framework.', $crawler->filter('html')->text()); + } + + /** + * Creates a topic + * + * Be sure to login before creating + * + * @param int $forum_id + * @param string $subject + * @param string $message + * @param array $additional_form_data Any additional form data to be sent in the request + * @return array post_id, topic_id + */ + public function create_topic($forum_id, $subject, $message, $additional_form_data = array()) + { + $posting_url = "posting.php?mode=post&f={$forum_id}&sid={$this->sid}"; + + $form_data = array_merge(array( + 'subject' => $subject, + 'message' => $message, + 'post' => true, + ), $additional_form_data); + + return $this->submit_post($posting_url, 'POST_TOPIC', $form_data); + } + + /** + * Creates a post + * + * Be sure to login before creating + * + * @param int $forum_id + * @param string $subject + * @param string $message + * @param array $additional_form_data Any additional form data to be sent in the request + * @return array post_id, topic_id + */ + public function create_post($forum_id, $topic_id, $subject, $message, $additional_form_data = array()) + { + $posting_url = "posting.php?mode=reply&f={$forum_id}&t={$topic_id}&sid={$this->sid}"; + + $form_data = array_merge(array( + 'subject' => $subject, + 'message' => $message, + 'post' => true, + ), $additional_form_data); + + return $this->submit_post($posting_url, 'POST_REPLY', $form_data); + } + + /** + * Helper for submitting posts + * + * @param string $posting_url + * @param string $posting_contains + * @param array $form_data + * @return array post_id, topic_id + */ + protected function submit_post($posting_url, $posting_contains, $form_data) + { + $this->add_lang('posting'); + + $crawler = $this->request('GET', $posting_url); + $this->assert_response_success(); + $this->assertContains($this->lang($posting_contains), $crawler->filter('html')->text()); + + $hidden_fields = array( + $crawler->filter('[type="hidden"]')->each(function ($node, $i) { + return array('name' => $node->getAttribute('name'), 'value' => $node->getAttribute('value')); + }), + ); + + foreach ($hidden_fields as $fields) + { + foreach($fields as $field) + { + $form_data[$field['name']] = $field['value']; + } + } + + // Bypass time restriction that said that if the lastclick time (i.e. time when the form was opened) + // is not at least 2 seconds before submission, cancel the form + $form_data['lastclick'] = 0; + + // I use a request because the form submission method does not allow you to send data that is not + // contained in one of the actual form fields that the browser sees (i.e. it ignores "hidden" inputs) + // Instead, I send it as a request with the submit button "post" set to true. + $crawler = $this->client->request('POST', $posting_url, $form_data); + $this->assert_response_success(); + $this->assertContains($this->lang('POST_STORED'), $crawler->filter('html')->text()); + + $url = $crawler->selectLink($this->lang('VIEW_MESSAGE', '', ''))->link()->getUri(); + + $matches = $topic_id = $post_id = false; + preg_match_all('#&t=([0-9]+)(&p=([0-9]+))?#', $url, $matches); + + $topic_id = (int) (isset($matches[1][0])) ? $matches[1][0] : 0; + $post_id = (int) (isset($matches[3][0])) ? $matches[3][0] : 0; + + return array( + 'topic_id' => $topic_id, + 'post_id' => $post_id, + ); + } +} diff --git a/tests/functions/clean_path_test.php b/tests/functions/clean_path_test.php new file mode 100644 index 0000000000..bcbe9838d9 --- /dev/null +++ b/tests/functions/clean_path_test.php @@ -0,0 +1,44 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_clean_path_test extends phpbb_test_case +{ + public function clean_path_test_data() + { + return array( + array('foo', 'foo'), + array('foo/bar', 'foo/bar'), + array('foo/bar/', 'foo/bar/'), + array('foo/./bar', 'foo/bar'), + array('foo/./././bar', 'foo/bar'), + array('foo/bar/.', 'foo/bar'), + array('./foo/bar', './foo/bar'), + array('../foo/bar', '../foo/bar'), + array('one/two/three', 'one/two/three'), + array('one/two/../three', 'one/three'), + array('one/../two/three', 'two/three'), + array('one/two/..', 'one'), + array('one/two/../', 'one/'), + array('one/two/../three/../four', 'one/four'), + array('one/two/three/../../four', 'one/four'), + ); + } + + /** + * @dataProvider clean_path_test_data + */ + public function test_clean_path($input, $expected) + { + $output = phpbb_clean_path($input); + + $this->assertEquals($expected, $output); + } +} diff --git a/tests/functions/get_formatted_filesize_test.php b/tests/functions/get_formatted_filesize_test.php new file mode 100644 index 0000000000..96ea2be132 --- /dev/null +++ b/tests/functions/get_formatted_filesize_test.php @@ -0,0 +1,71 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_get_formatted_filesize_test extends phpbb_test_case +{ + public function get_formatted_filesize_test_data() + { + return array( + // exact powers of 2 + array(1, '1 BYTES'), + array(1024, '1 KIB'), + array(1048576, '1 MIB'), + array(1073741824, '1 GIB'), + array(1099511627776, '1 TIB'), + + // exact powers of 10 + array(1000, '1000 BYTES'), + array(1000000, '976.56 KIB'), + array(1000000000, '953.67 MIB'), + array(1000000000000, '931.32 GIB'), + array(100000000000000, '90.95 TIB'), + + array(0, '0 BYTES'), + array(2, '2 BYTES'), + + array(1023, '1023 BYTES'), + array(1025, '1 KIB'), + array(1048575, '1024 KIB'), + + // String values + // exact powers of 2 + array('1', '1 BYTES'), + array('1024', '1 KIB'), + array('1048576', '1 MIB'), + array('1073741824', '1 GIB'), + array('1099511627776', '1 TIB'), + + // exact powers of 10 + array('1000', '1000 BYTES'), + array('1000000', '976.56 KIB'), + array('1000000000', '953.67 MIB'), + array('1000000000000', '931.32 GIB'), + array('100000000000000', '90.95 TIB'), + + array('0', '0 BYTES'), + array('2', '2 BYTES'), + + array('1023', '1023 BYTES'), + array('1025', '1 KIB'), + array('1048575', '1024 KIB'), + ); + } + + /** + * @dataProvider get_formatted_filesize_test_data + */ + public function test_get_formatted_filesize($input, $expected) + { + $output = get_formatted_filesize($input); + + $this->assertEquals($expected, $output); + } +} diff --git a/tests/functions_database_helper/fixtures/bookmarks_duplicates.xml b/tests/functions_database_helper/fixtures/bookmarks_duplicates.xml new file mode 100644 index 0000000000..d49f76b073 --- /dev/null +++ b/tests/functions_database_helper/fixtures/bookmarks_duplicates.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> + <table name="phpbb_bookmarks"> + <column>user_id</column> + <column>topic_id</column> + + <!-- one entry for this topic --> + <row> + <value>1</value> + <value>1</value> + </row> + + <!-- non-conflicting entries --> + <row> + <value>2</value> + <value>2</value> + </row> + <row> + <value>3</value> + <value>3</value> + </row> + + <!-- conflicting entries --> + <row> + <value>1</value> + <value>4</value> + </row> + <row> + <value>1</value> + <value>5</value> + </row> + + <!-- conflicting and non-conflicting entries --> + <row> + <value>1</value> + <value>6</value> + </row> + <row> + <value>1</value> + <value>7</value> + </row> + <row> + <value>2</value> + <value>6</value> + </row> + </table> +</dataset> diff --git a/tests/functions_database_helper/fixtures/topics_watch_duplicates.xml b/tests/functions_database_helper/fixtures/topics_watch_duplicates.xml new file mode 100644 index 0000000000..c387bb737a --- /dev/null +++ b/tests/functions_database_helper/fixtures/topics_watch_duplicates.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> + <table name="phpbb_topics_watch"> + <column>user_id</column> + <column>topic_id</column> + <column>notify_status</column> + + <!-- one entry for this topic --> + <row> + <value>1</value> + <value>1</value> + <value>1</value> + </row> + + <!-- non-conflicting entries --> + <row> + <value>1</value> + <value>2</value> + <value>1</value> + </row> + <row> + <value>2</value> + <value>3</value> + <value>0</value> + </row> + + <!-- conflicting entries, same notify status --> + <row> + <value>1</value> + <value>4</value> + <value>1</value> + </row> + <row> + <value>1</value> + <value>5</value> + <value>1</value> + </row> + + <!-- conflicting entries, notify status 0 into 1 --> + <row> + <value>1</value> + <value>6</value> + <value>0</value> + </row> + <row> + <value>1</value> + <value>7</value> + <value>1</value> + </row> + + <!-- conflicting entries, notify status 1 into 0 --> + <row> + <value>1</value> + <value>8</value> + <value>1</value> + </row> + <row> + <value>1</value> + <value>9</value> + <value>0</value> + </row> + + <!-- conflicting and non-conflicting entries --> + <row> + <value>1</value> + <value>10</value> + <value>0</value> + </row> + <row> + <value>1</value> + <value>11</value> + <value>1</value> + </row> + <row> + <value>2</value> + <value>10</value> + <value>1</value> + </row> + </table> +</dataset> diff --git a/tests/functions_database_helper/update_rows_avoiding_duplicates_notify_status_test.php b/tests/functions_database_helper/update_rows_avoiding_duplicates_notify_status_test.php new file mode 100644 index 0000000000..d4881daf7e --- /dev/null +++ b/tests/functions_database_helper/update_rows_avoiding_duplicates_notify_status_test.php @@ -0,0 +1,101 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_database_helper.php'; + +class phpbb_update_rows_avoiding_duplicates_notify_status_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/topics_watch_duplicates.xml'); + } + + public static function fixture_data() + { + return array( + // description + // from array + // to value + // expected count with to value post update + // expected notify_status values + array( + 'trivial', + array(1), + 1000, + 1, + 1, + ), + array( + 'no conflict', + array(2), + 3, + 2, + 1, + ), + array( + 'conflict, same notify status', + array(4), + 5, + 1, + 1, + ), + array( + 'conflict, notify status 0 into 1', + array(6), + 7, + 1, + 0, + ), + array( + 'conflict, notify status 1 into 0', + array(8), + 9, + 1, + 0, + ), + array( + 'conflict and no conflict', + array(10), + 11, + 2, + 0, + ), + ); + } + + /** + * @dataProvider fixture_data + */ + public function test_update($description, $from, $to, $expected_result_count, $expected_notify_status) + { + $db = $this->new_dbal(); + + phpbb_update_rows_avoiding_duplicates_notify_status($db, TOPICS_WATCH_TABLE, 'topic_id', $from, $to); + + $sql = 'SELECT COUNT(*) AS remaining_rows + FROM ' . TOPICS_WATCH_TABLE . ' + WHERE topic_id = ' . (int) $to; + $result = $db->sql_query($sql); + $result_count = $db->sql_fetchfield('remaining_rows'); + $db->sql_freeresult($result); + + $this->assertEquals($expected_result_count, $result_count); + + // user id of 1 is the user being updated + $sql = 'SELECT notify_status + FROM ' . TOPICS_WATCH_TABLE . ' + WHERE topic_id = ' . (int) $to . ' + AND user_id = 1'; + $result = $db->sql_query($sql); + $notify_status = $db->sql_fetchfield('notify_status'); + $db->sql_freeresult($result); + + $this->assertEquals($expected_notify_status, $notify_status); + } +} diff --git a/tests/functions_database_helper/update_rows_avoiding_duplicates_test.php b/tests/functions_database_helper/update_rows_avoiding_duplicates_test.php new file mode 100644 index 0000000000..2f01d29d15 --- /dev/null +++ b/tests/functions_database_helper/update_rows_avoiding_duplicates_test.php @@ -0,0 +1,71 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_database_helper.php'; + +class phpbb_update_rows_avoiding_duplicates_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/bookmarks_duplicates.xml'); + } + + public static function fixture_data() + { + return array( + // description + // from array + // to value + // expected count with to value post update + array( + 'trivial', + array(1), + 10, + 1, + ), + array( + 'no conflict', + array(2), + 3, + 2, + ), + array( + 'conflict', + array(4), + 5, + 1, + ), + array( + 'conflict and no conflict', + array(6), + 7, + 2, + ), + ); + } + + /** + * @dataProvider fixture_data + */ + public function test_update($description, $from, $to, $expected_result_count) + { + $db = $this->new_dbal(); + + phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $from, $to); + + $sql = 'SELECT COUNT(*) AS remaining_rows + FROM ' . BOOKMARKS_TABLE . ' + WHERE topic_id = ' . (int) $to; + $result = $db->sql_query($sql); + $result_count = $db->sql_fetchfield('remaining_rows'); + $db->sql_freeresult($result); + + $this->assertEquals($expected_result_count, $result_count); + } +} diff --git a/tests/lint_test.php b/tests/lint_test.php new file mode 100644 index 0000000000..905067072d --- /dev/null +++ b/tests/lint_test.php @@ -0,0 +1,74 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +class phpbb_lint_test extends phpbb_test_case +{ + static protected $exclude; + + static public function setUpBeforeClass() + { + $output = array(); + $status = 1; + exec('(php -v) 2>&1', $output, $status); + if ($status) + { + $output = implode("\n", $output); + self::markTestSkipped("php is not in PATH or broken: $output"); + } + + self::$exclude = array( + // PHP Fatal error: Cannot declare class Container because the name is already in use in /var/www/projects/phpbb3/tests/../phpBB/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php on line 20 + // https://gist.github.com/e003913ffd493da63cbc + dirname(__FILE__) . '/../phpBB/vendor', + ); + } + + public function test_lint() + { + if (version_compare(PHP_VERSION, '5.3.0', '<')) + { + $this->markTestSkipped('phpBB uses PHP 5.3 syntax in some files, linting on PHP < 5.3 will fail'); + } + + $root = dirname(__FILE__) . '/..'; + $this->check($root); + } + + protected function check($root) + { + $dh = opendir($root); + while (($filename = readdir($dh)) !== false) + { + if ($filename == '.' || $filename == '..' || $filename == 'git') + { + continue; + } + $path = $root . '/' . $filename; + // skip symlinks to avoid infinite loops + if (is_link($path)) + { + continue; + } + if (is_dir($path) && !in_array($path, self::$exclude)) + { + $this->check($path); + } + else if (substr($filename, strlen($filename)-4) == '.php') + { + // assume php binary is called php and it is in PATH + $cmd = '(php -l ' . escapeshellarg($path) . ') 2>&1'; + $output = array(); + $status = 1; + exec($cmd, $output, $status); + $output = implode("\n", $output); + $this->assertEquals(0, $status, "php -l failed for $path:\n$output"); + } + } + } +} diff --git a/tests/mock/cache.php b/tests/mock/cache.php index 650545c3d6..aa0db5ab20 100644 --- a/tests/mock/cache.php +++ b/tests/mock/cache.php @@ -34,6 +34,16 @@ class phpbb_mock_cache $this->data[$var_name] = $var; } + public function destroy($var_name, $table = '') + { + if ($table) + { + throw new Exception('Destroying tables is not implemented yet'); + } + + unset($this->data[$var_name]); + } + /** * Obtain active bots */ @@ -41,7 +51,7 @@ class phpbb_mock_cache { return $this->data['_bots']; } - + /** * Obtain list of word censors. We don't need to parse them here, * that is tested elsewhere. diff --git a/tests/mock/null_cache.php b/tests/mock/null_cache.php new file mode 100644 index 0000000000..aca20ca77b --- /dev/null +++ b/tests/mock/null_cache.php @@ -0,0 +1,42 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +class phpbb_mock_null_cache +{ + public function __construct() + { + } + + public function get($var_name) + { + return false; + } + + public function put($var_name, $var, $ttl = 0) + { + } + + public function destroy($var_name, $table = '') + { + } + + public function obtain_bots() + { + return array(); + } + + public function obtain_word_list() + { + return array(); + } + + public function set_bots($bots) + { + } +} diff --git a/tests/mock_user.php b/tests/mock/user.php index ec14ce430e..ec14ce430e 100644 --- a/tests/mock_user.php +++ b/tests/mock/user.php diff --git a/tests/privmsgs/delete_user_pms_test.php b/tests/privmsgs/delete_user_pms_test.php new file mode 100644 index 0000000000..f705825262 --- /dev/null +++ b/tests/privmsgs/delete_user_pms_test.php @@ -0,0 +1,102 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_privmsgs.php'; + +class phpbb_privmsgs_delete_user_pms_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/delete_user_pms.xml'); + } + + static public function delete_user_pms_data() + { + return array( + // array( + // (user we delete), + // array(remaining privmsgs ids), + // array(remaining privmsgs_to), + // ), + array( + 2, + array( + array('msg_id' => 1), + ), + array( + array('msg_id' => 1, 'user_id' => 3), + ), + ), + array( + 3, + array( + array('msg_id' => 1), + array('msg_id' => 2), + array('msg_id' => 3), + array('msg_id' => 5), + ), + array( + array('msg_id' => 1, 'user_id' => 2), + array('msg_id' => 1, 'user_id' => 4), + array('msg_id' => 2, 'user_id' => 2), + array('msg_id' => 2, 'user_id' => 4), + array('msg_id' => 3, 'user_id' => 2), + array('msg_id' => 5, 'user_id' => 2), + array('msg_id' => 5, 'user_id' => 4), + ), + ), + array( + 5, + array( + array('msg_id' => 1), + array('msg_id' => 2), + array('msg_id' => 3), + array('msg_id' => 4), + array('msg_id' => 5), + ), + array( + array('msg_id' => 1, 'user_id' => 2), + array('msg_id' => 1, 'user_id' => 3), + array('msg_id' => 1, 'user_id' => 4), + array('msg_id' => 2, 'user_id' => 2), + array('msg_id' => 2, 'user_id' => 4), + array('msg_id' => 3, 'user_id' => 2), + array('msg_id' => 4, 'user_id' => 3), + array('msg_id' => 5, 'user_id' => 2), + array('msg_id' => 5, 'user_id' => 3), + array('msg_id' => 5, 'user_id' => 4), + ), + ), + ); + } + + /** + * @dataProvider delete_user_pms_data + */ + public function test_delete_user_pms($delete_user, $remaining_privmsgs, $remaining_privmsgs_to) + { + global $db; + + $db = $this->new_dbal(); + + phpbb_delete_user_pms($delete_user); + + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TABLE; + $result = $db->sql_query($sql); + + $this->assertEquals($remaining_privmsgs, $db->sql_fetchrowset($result)); + + $sql = 'SELECT msg_id, user_id + FROM ' . PRIVMSGS_TO_TABLE; + $result = $db->sql_query($sql); + + $this->assertEquals($remaining_privmsgs_to, $db->sql_fetchrowset($result)); + } +} diff --git a/tests/privmsgs/fixtures/delete_user_pms.xml b/tests/privmsgs/fixtures/delete_user_pms.xml new file mode 100644 index 0000000000..9a86501b7a --- /dev/null +++ b/tests/privmsgs/fixtures/delete_user_pms.xml @@ -0,0 +1,215 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> + <table name="phpbb_users"> + <column>user_id</column> + <column>username</column> + <column>username_clean</column> + <column>user_new_privmsg</column> + <column>user_unread_privmsg</column> + <column>user_permissions</column> + <column>user_sig</column> + <column>user_occ</column> + <column>user_interests</column> + <row> + <value>2</value> + <value>sender</value> + <value>sender</value> + <value>0</value> + <value>0</value> + <value></value> + <value></value> + <value></value> + <value></value> + </row> + <row> + <value>3</value> + <value>pm in inbox</value> + <value>pm in inbox</value> + <value>0</value> + <value>0</value> + <value></value> + <value></value> + <value></value> + <value></value> + </row> + <row> + <value>4</value> + <value>pm in no box</value> + <value>pm in no box</value> + <value>2</value> + <value>2</value> + <value></value> + <value></value> + <value></value> + <value></value> + </row> + <row> + <value>5</value> + <value>no pms</value> + <value>no pms</value> + <value>0</value> + <value>0</value> + <value></value> + <value></value> + <value></value> + <value></value> + </row> + </table> + <table name="phpbb_privmsgs"> + <column>msg_id</column> + <column>root_level</column> + <column>author_id</column> + <column>message_subject</column> + <column>message_text</column> + <column>to_address</column> + <column>bcc_address</column> + <row> + <value>1</value> + <value>0</value> + <value>2</value> + <value>#1</value> + <value> + 2 - outbox + 3 - inbox + 4 - nobox + </value> + <value></value> + <value></value> + </row> + <row> + <value>2</value> + <value>0</value> + <value>2</value> + <value>#2</value> + <value> + 2 - outbox + 4 - nobox + </value> + <value></value> + <value></value> + </row> + <row> + <value>3</value> + <value>0</value> + <value>2</value> + <value>#3</value> + <value> + 2 - outbox + </value> + <value></value> + <value></value> + </row> + <row> + <value>4</value> + <value>0</value> + <value>2</value> + <value>#4</value> + <value> + 3 - nobox + </value> + <value></value> + <value></value> + </row> + <row> + <value>5</value> + <value>0</value> + <value>2</value> + <value>#5</value> + <value> + 2 - outbox + 3 - nobox + 4 - nobox + </value> + <value></value> + <value></value> + </row> + </table> + <table name="phpbb_privmsgs_to"> + <column>msg_id</column> + <column>user_id</column> + <column>author_id</column> + <column>pm_new</column> + <column>pm_unread</column> + <column>folder_id</column> + <row> + <value>1</value> + <value>2</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-2</value> + </row> + <row> + <value>1</value> + <value>3</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>0</value> + </row> + <row> + <value>1</value> + <value>4</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-3</value> + </row> + <row> + <value>2</value> + <value>2</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-2</value> + </row> + <row> + <value>2</value> + <value>4</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-3</value> + </row> + <row> + <value>3</value> + <value>2</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-2</value> + </row> + <row> + <value>4</value> + <value>3</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-3</value> + </row> + <row> + <value>5</value> + <value>2</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-2</value> + </row> + <row> + <value>5</value> + <value>3</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-3</value> + </row> + <row> + <value>5</value> + <value>4</value> + <value>2</value> + <value>0</value> + <value>0</value> + <value>-3</value> + </row> + </table> +</dataset> diff --git a/tests/regex/email_test.php b/tests/regex/email_test.php index 17f93259c3..b4ea5b23aa 100644 --- a/tests/regex/email_test.php +++ b/tests/regex/email_test.php @@ -28,6 +28,8 @@ class phpbb_regex_email_test extends phpbb_test_case array('alice_foo@bar.phpbb.com'), array('alice+tag@foo.phpbb.com'), array('alice&tag@foo.phpbb.com'), + array('alice@phpbb.australia'), + array('alice@phpbb.topZlevelZdomainZnamesZcanZbeZupZtoZsixtyZthreeZcharactersZlong'), //array('"John Doe"@example.com'), //array('Alice@[192.168.2.1]'), // IPv4 @@ -96,6 +98,7 @@ class phpbb_regex_email_test extends phpbb_test_case array('! "#$%(),/;<>[]`|@invalidCharsInLocal.org'), array('invalidCharsInDomain@! "#$%(),/;<>_[]`|.org'), array('local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org'), + array('alice@phpbb.topZlevelZdomainZnamesZcanZbeZupZtoZsixtyZthreeZcharactersZlongZ'), ); } diff --git a/tests/request/request_var_test.php b/tests/request/request_var_test.php index 8e609c00af..0c07fe11a3 100644 --- a/tests/request/request_var_test.php +++ b/tests/request/request_var_test.php @@ -73,7 +73,7 @@ class phpbb_request_request_var_test extends phpbb_test_case unset($_GET[$var], $_POST[$var], $_REQUEST[$var], $_COOKIE[$var]); } - public static function request_variables() + static public function request_variables() { return array( // strings diff --git a/tests/security/extract_current_page_test.php b/tests/security/extract_current_page_test.php index 4911f7b452..0f5128884b 100644 --- a/tests/security/extract_current_page_test.php +++ b/tests/security/extract_current_page_test.php @@ -14,7 +14,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/session.php'; class phpbb_security_extract_current_page_test extends phpbb_security_test_base { - public static function security_variables() + static public function security_variables() { return array( array('http://localhost/phpBB/index.php', 'mark=forums&x="><script>alert(/XSS/);</script>', 'mark=forums&x=%22%3E%3Cscript%3Ealert(/XSS/);%3C/script%3E'), diff --git a/tests/security/redirect_test.php b/tests/security/redirect_test.php index 4848a938c6..872a331dc7 100644 --- a/tests/security/redirect_test.php +++ b/tests/security/redirect_test.php @@ -14,7 +14,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/session.php'; class phpbb_security_redirect_test extends phpbb_security_test_base { - public static function provider() + static public function provider() { // array(Input -> redirect(), expected triggered error (else false), expected returned result url (else false)) return array( diff --git a/tests/session/append_sid_test.php b/tests/session/append_sid_test.php index 88f6f0718e..ce7bf71215 100644 --- a/tests/session/append_sid_test.php +++ b/tests/session/append_sid_test.php @@ -1,51 +1,50 @@ -<?php
-/**
-*
-* @package testing
-* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-*
-*/
-
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-
-class phpbb_session_append_sid_test extends phpbb_test_case
-{
-
- public function append_sid_data()
- {
- return array(
- array('viewtopic.php?t=1&f=2', false, true, false, 'viewtopic.php?t=1&f=2', 'parameters in url-argument'),
- array('viewtopic.php', 't=1&f=2', true, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument using amp'),
- array('viewtopic.php', 't=1&f=2', false, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument using &'),
- array('viewtopic.php', array('t' => 1, 'f' => 2), true, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument as array'),
-
- // Custom sid parameter
- array('viewtopic.php', 't=1&f=2', true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid', 'using session_id'),
-
- // Testing anchors
- array('viewtopic.php?t=1&f=2#anchor', false, true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in url-argument'),
- array('viewtopic.php', 't=1&f=2#anchor', true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in params-argument'),
- array('viewtopic.php', array('t' => 1, 'f' => 2, '#' => 'anchor'), true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in params-argument (array)'),
-
- // Anchors and custom sid
- array('viewtopic.php?t=1&f=2#anchor', false, true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in url-argument using session_id'),
- array('viewtopic.php', 't=1&f=2#anchor', true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in params-argument using session_id'),
- array('viewtopic.php', array('t' => 1, 'f' => 2, '#' => 'anchor'), true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in params-argument (array) using session_id'),
-
- // Empty parameters should not append the ?
- array('viewtopic.php', false, true, false, 'viewtopic.php', 'no params using bool false'),
- array('viewtopic.php', '', true, false, 'viewtopic.php', 'no params using empty string'),
- array('viewtopic.php', array(), true, false, 'viewtopic.php', 'no params using empty array'),
- );
- }
-
- /**
- * @dataProvider append_sid_data
- */
- public function test_append_sid($url, $params, $is_amp, $session_id, $expected, $description)
- {
- $this->assertEquals($expected, append_sid($url, $params, $is_amp, $session_id));
- }
-}
-
+<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_session_append_sid_test extends phpbb_test_case +{ + + public function append_sid_data() + { + return array( + array('viewtopic.php?t=1&f=2', false, true, false, 'viewtopic.php?t=1&f=2', 'parameters in url-argument'), + array('viewtopic.php', 't=1&f=2', true, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument using amp'), + array('viewtopic.php', 't=1&f=2', false, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument using &'), + array('viewtopic.php', array('t' => 1, 'f' => 2), true, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument as array'), + + // Custom sid parameter + array('viewtopic.php', 't=1&f=2', true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid', 'using session_id'), + + // Testing anchors + array('viewtopic.php?t=1&f=2#anchor', false, true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in url-argument'), + array('viewtopic.php', 't=1&f=2#anchor', true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in params-argument'), + array('viewtopic.php', array('t' => 1, 'f' => 2, '#' => 'anchor'), true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in params-argument (array)'), + + // Anchors and custom sid + array('viewtopic.php?t=1&f=2#anchor', false, true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in url-argument using session_id'), + array('viewtopic.php', 't=1&f=2#anchor', true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in params-argument using session_id'), + array('viewtopic.php', array('t' => 1, 'f' => 2, '#' => 'anchor'), true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in params-argument (array) using session_id'), + + // Empty parameters should not append the ? + array('viewtopic.php', false, true, false, 'viewtopic.php', 'no params using bool false'), + array('viewtopic.php', '', true, false, 'viewtopic.php', 'no params using empty string'), + array('viewtopic.php', array(), true, false, 'viewtopic.php', 'no params using empty array'), + ); + } + + /** + * @dataProvider append_sid_data + */ + public function test_append_sid($url, $params, $is_amp, $session_id, $expected, $description) + { + $this->assertEquals($expected, append_sid($url, $params, $is_amp, $session_id)); + } +} diff --git a/tests/template/template_test.php b/tests/template/template_test.php index aaee7bb4a0..291b424bdd 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -94,7 +94,7 @@ class phpbb_template_template_test extends phpbb_test_case /** * @todo put test data into templates/xyz.test */ - public static function template_data() + static public function template_data() { return array( /* @@ -238,7 +238,22 @@ class phpbb_template_template_test extends phpbb_test_case array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())), array('loop'), '', - ),/* no top level nested loops + ), + array( + 'include_define_variable.html', + array('VARIABLE' => 'variable.html'), + array(), + array(), + 'variable.html', + ), + array( + 'include_loop_define.html', + array('VARIABLE' => 'value'), + array('loop' => array(array('NESTED_FILE' => 'variable.html'))), + array(), + 'value', + ), + /* no top level nested loops array( 'loop_vars.html', array(), @@ -419,7 +434,7 @@ class phpbb_template_template_test extends phpbb_test_case $GLOBALS['config']['tpl_allow_php'] = false; } - public static function alter_block_array_data() + static public function alter_block_array_data() { return array( array( diff --git a/tests/template/templates/include_define_variable.html b/tests/template/templates/include_define_variable.html new file mode 100644 index 0000000000..aff9b574c2 --- /dev/null +++ b/tests/template/templates/include_define_variable.html @@ -0,0 +1,2 @@ +<!-- DEFINE $DEF = '{VARIABLE}' --> +<!-- INCLUDE {$DEF} --> diff --git a/tests/template/templates/include_loop_define.html b/tests/template/templates/include_loop_define.html new file mode 100644 index 0000000000..f539b21396 --- /dev/null +++ b/tests/template/templates/include_loop_define.html @@ -0,0 +1,4 @@ +<!-- BEGIN loop --> +<!-- DEFINE $DEF = '{loop.NESTED_FILE}' --> +<!-- INCLUDE {$DEF} --> +<!-- END loop --> 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..429bb92bf1 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -13,6 +13,8 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test protected $test_case_helpers; + protected $fixture_xml_data; + public function __construct($name = NULL, array $data = array(), $dataName = '') { parent::__construct($name, $data, $dataName); @@ -28,6 +30,44 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test ); } + protected function setUp() + { + parent::setUp(); + + // Resynchronise tables if a fixture was loaded + if (isset($this->fixture_xml_data)) + { + $config = $this->get_database_config(); + $manager = $this->create_connection_manager($config); + $manager->connect(); + $manager->post_setup_synchronisation($this->fixture_xml_data); + } + } + + 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']; + } + + $this->fixture_xml_data = parent::createXMLDataSet($path); + + return $this->fixture_xml_data; + } + public function get_test_case_helpers() { if (!$this->test_case_helpers) @@ -106,4 +146,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 + */ + static public 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 c734c90a1a..d7c2804aa7 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']; @@ -80,12 +88,52 @@ class phpbb_database_test_connection_manager { $dsn .= ';dbname=' . $this->config['dbname']; } + else if ($this->dbms['PDO'] == 'pgsql') + { + // Postgres always connects to a + // database. If the database is not + // specified here, but the username + // is specified, then connection + // will be to the database named + // as the username. + // + // For greater compatibility, connect + // instead to postgres database which + // should always exist: + // http://www.postgresql.org/docs/9.0/static/manage-ag-templatedbs.html + $dsn .= ';dbname=postgres'; + } 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) { @@ -93,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); } /** @@ -119,10 +166,24 @@ class phpbb_database_test_connection_manager switch ($this->config['dbms']) { case 'sqlite': - if (file_exists($this->config['dbhost'])) + 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) { - unlink($this->config['dbhost']); + $this->pdo->exec('DROP TABLE ' . $table . ' CASCADE CONSTRAINTS'); } + $this->purge_extras(); break; default: @@ -131,6 +192,15 @@ class phpbb_database_test_connection_manager 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) { @@ -139,9 +209,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; } } @@ -243,7 +312,7 @@ class phpbb_database_test_connection_manager $filename = $directory . $schema . '_schema.sql'; $queries = file_get_contents($filename); - $sql = remove_comments($queries); + $sql = phpbb_remove_comments($queries); $sql = split_sql_file($sql, $this->dbms['DELIM']); @@ -317,4 +386,151 @@ 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); + } + } + + /** + * Performs synchronisations on the database after a fixture has been loaded + * + * @param PHPUnit_Extensions_Database_DataSet_XmlDataSet $xml_data_set Information about the tables contained within the loaded fixture + * + * @return null + */ + public function post_setup_synchronisation($xml_data_set) + { + $this->ensure_connected(__METHOD__); + $queries = array(); + + // Get escaped versions of the table names used in the fixture + $table_names = array_map(array($this->pdo, 'PDO::quote'), $xml_data_set->getTableNames()); + + switch ($this->config['dbms']) + { + case 'oracle': + // Get all of the information about the sequences + $sql = "SELECT t.table_name, tc.column_name, d.referenced_name as sequence_name, s.increment_by, s.min_value + FROM USER_TRIGGERS t + JOIN USER_DEPENDENCIES d ON (d.name = t.trigger_name) + JOIN USER_TRIGGER_COLS tc ON (tc.trigger_name = t.trigger_name) + JOIN USER_SEQUENCES s ON (s.sequence_name = d.referenced_name) + WHERE d.referenced_type = 'SEQUENCE' + AND d.type = 'TRIGGER' + AND t.table_name IN (" . implode(', ', array_map('strtoupper', $table_names)) . ')'; + + $result = $this->pdo->query($sql); + + while ($row = $result->fetch(PDO::FETCH_ASSOC)) + { + // Get the current max value of the table + $sql = "SELECT MAX({$row['COLUMN_NAME']}) AS max FROM {$row['TABLE_NAME']}"; + $max_result = $this->pdo->query($sql); + $max_row = $max_result->fetch(PDO::FETCH_ASSOC); + + if (!$max_row) + { + continue; + } + + $max_val = (int) $max_row['MAX']; + $max_val++; + + /** + * This is not the "proper" way, but the proper way does not allow you to completely reset + * tables with no rows since you have to select the next value to make the change go into effect. + * You would have to go past the minimum value to set it correctly, but that's illegal. + * Since we have no objects attached to our sequencers (triggers aren't attached), this works fine. + */ + $queries[] = 'DROP SEQUENCE ' . $row['SEQUENCE_NAME']; + $queries[] = "CREATE SEQUENCE {$row['SEQUENCE_NAME']} + MINVALUE {$row['MIN_VALUE']} + INCREMENT BY {$row['INCREMENT_BY']} + START WITH $max_val"; + } + break; + + case 'postgres': + // Get the sequences attached to the tables + $sql = 'SELECT column_name, table_name FROM information_schema.columns + WHERE table_name IN (' . implode(', ', $table_names) . ") + AND strpos(column_default, '_seq''::regclass') > 0"; + $result = $this->pdo->query($sql); + + $setval_queries = array(); + while ($row = $result->fetch(PDO::FETCH_ASSOC)) + { + // Get the columns used in the fixture for this table + $column_names = $xml_data_set->getTableMetaData($row['table_name'])->getColumns(); + + // Skip sequences that weren't specified in the fixture + if (!in_array($row['column_name'], $column_names)) + { + continue; + } + + // Get the old value if it exists, or use 1 if it doesn't + $sql = "SELECT COALESCE((SELECT MAX({$row['column_name']}) + 1 FROM {$row['table_name']}), 1) AS val"; + $result_max = $this->pdo->query($sql); + $row_max = $result_max->fetch(PDO::FETCH_ASSOC); + + if ($row_max) + { + $seq_name = $this->pdo->quote($row['table_name'] . '_seq'); + $max_val = (int) $row_max['val']; + + // The last parameter is false so that the system doesn't increment it again + $setval_queries[] = "SETVAL($seq_name, $max_val, false)"; + } + } + + // Combine all of the SETVALs into one query + if (sizeof($setval_queries)) + { + $queries[] = 'SELECT ' . implode(', ', $setval_queries); + } + break; + } + + foreach ($queries as $query) + { + $this->pdo->exec($query); + } + } } diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index b5e6f7e377..8ab6469e9a 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -6,36 +6,70 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 * */ +use Symfony\Component\BrowserKit\CookieJar; require_once __DIR__ . '/../../phpBB/includes/functions_install.php'; +require_once __DIR__ . '/../../phpBB/includes/acm/acm_file.php'; +require_once __DIR__ . '/../../phpBB/includes/cache.php'; class phpbb_functional_test_case extends phpbb_test_case { protected $client; protected $root_url; + protected $cache = null; + protected $db = null; + + /** + * Session ID for current test's session (each test makes its own) + * @var string + */ + protected $sid; + + /** + * Language array used by phpBB + * @var array + */ + protected $lang = array(); + static protected $config = array(); static protected $already_installed = false; static public function setUpBeforeClass() { - if (!extension_loaded('phar')) + parent::setUpBeforeClass(); + + self::$config = phpbb_test_case_helpers::get_test_config(); + + if (!isset(self::$config['phpbb_functional_url'])) { - self::markTestSkipped('phar extension is not loaded'); + self::markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.'); } - require_once 'phar://' . __DIR__ . '/../../vendor/goutte.phar'; + if (!self::$already_installed) + { + self::install_board(); + self::$already_installed = true; + } } public function setUp() { - if (!isset(self::$config['phpbb_functional_url'])) - { - $this->markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.'); - } + parent::setUp(); - $this->client = new Goutte\Client(); + $this->bootstrap(); + + $this->cookieJar = new CookieJar; + $this->client = new Goutte\Client(array(), null, $this->cookieJar); + // Reset the curl handle because it is 0 at this point and not a valid + // resource + $this->client->getClient()->getCurlMulti()->reset(true); $this->root_url = self::$config['phpbb_functional_url']; + // Clear the language array so that things + // that were added in other tests are gone + $this->lang = array(); + $this->add_lang('common'); + $this->purge_cache(); } public function request($method, $path) @@ -50,6 +84,42 @@ class phpbb_functional_test_case extends phpbb_test_case { } + protected function get_db() + { + global $phpbb_root_path, $phpEx; + // so we don't reopen an open connection + if (!($this->db instanceof dbal)) + { + if (!class_exists('dbal_' . self::$config['dbms'])) + { + include($phpbb_root_path . 'includes/db/' . self::$config['dbms'] . ".$phpEx"); + } + $sql_db = 'dbal_' . self::$config['dbms']; + $this->db = new $sql_db(); + $this->db->sql_connect(self::$config['dbhost'], self::$config['dbuser'], self::$config['dbpasswd'], self::$config['dbname'], self::$config['dbport']); + } + return $this->db; + } + + protected function get_cache_driver() + { + if (!$this->cache) + { + $this->cache = new cache(); + } + + return $this->cache; + } + + protected function purge_cache() + { + $cache = $this->get_cache_driver(); + + $cache->purge(); + $cache->unload(); + $cache->load(); + } + public function __construct($name = NULL, array $data = array(), $dataName = '') { parent::__construct($name, $data, $dataName); @@ -57,28 +127,14 @@ class phpbb_functional_test_case extends phpbb_test_case $this->backupStaticAttributesBlacklist += array( 'phpbb_functional_test_case' => array('config', 'already_installed'), ); - - if (!static::$already_installed) - { - $this->install_board(); - $this->bootstrap(); - static::$already_installed = true; - } } - protected function install_board() + static protected function install_board() { global $phpbb_root_path, $phpEx; - self::$config = phpbb_test_case_helpers::get_test_config(); - - if (!isset(self::$config['phpbb_functional_url'])) - { - return; - } - self::$config['table_prefix'] = 'phpbb_'; - $this->recreate_database(self::$config); + self::recreate_database(self::$config); if (file_exists($phpbb_root_path . "config.$phpEx")) { @@ -123,21 +179,28 @@ class phpbb_functional_test_case extends phpbb_test_case )); // end data - $content = $this->do_request('install'); - $this->assertContains('Welcome to Installation', $content); - - $this->do_request('create_table', $data); + $content = self::do_request('install'); + self::assertNotSame(false, $content); + self::assertContains('Welcome to Installation', $content); - file_put_contents($phpbb_root_path . "config.$phpEx", phpbb_create_config_file_data($data, self::$config['dbms'], array(), true)); + $content = self::do_request('create_table', $data); + self::assertNotSame(false, $content); + self::assertContains('The database tables used by phpBB', $content); + // 3.0 or 3.1 + self::assertContains('have been created and populated with some initial data.', $content); - $this->do_request('config_file', $data); + $content = self::do_request('config_file', $data); + self::assertNotSame(false, $content); + self::assertContains('Configuration file', $content); + file_put_contents($phpbb_root_path . "config.$phpEx", phpbb_create_config_file_data($data, self::$config['dbms'], array(), true, true)); + $content = self::do_request('final', $data); + self::assertNotSame(false, $content); + self::assertContains('You have successfully installed', $content); copy($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "config_test.$phpEx"); - - $this->do_request('final', $data); } - private function do_request($sub, $post_data = null) + static private function do_request($sub, $post_data = null) { $context = null; @@ -156,9 +219,135 @@ class phpbb_functional_test_case extends phpbb_test_case return file_get_contents(self::$config['phpbb_functional_url'] . 'install/index.php?mode=install&sub=' . $sub, false, $context); } - private function recreate_database($config) + static private function recreate_database($config) { $db_conn_mgr = new phpbb_database_test_connection_manager($config); $db_conn_mgr->recreate_db(); } + + /** + * Creates a new user with limited permissions + * + * @param string $username Also doubles up as the user's password + * @return int ID of created user + */ + protected function create_user($username) + { + // Required by unique_id + global $config; + + if (!is_array($config)) + { + $config = array(); + } + + $config['rand_seed'] = ''; + $config['rand_seed_last_update'] = time() + 600; + + // Required by user_add + global $db, $cache; + $db = $this->get_db(); + if (!function_exists('phpbb_mock_null_cache')) + { + require_once(__DIR__ . '/../mock/null_cache.php'); + } + $cache = new phpbb_mock_null_cache; + + if (!function_exists('utf_clean_string')) + { + require_once(__DIR__ . '/../../phpBB/includes/utf/utf_tools.php'); + } + if (!function_exists('user_add')) + { + require_once(__DIR__ . '/../../phpBB/includes/functions_user.php'); + } + + $user_row = array( + 'username' => $username, + 'group_id' => 2, + 'user_email' => 'nobody@example.com', + 'user_type' => 0, + 'user_lang' => 'en', + 'user_timezone' => 0, + 'user_dateformat' => '', + 'user_password' => phpbb_hash($username), + ); + return user_add($user_row); + } + + protected function login($username = 'admin') + { + $this->add_lang('ucp'); + + $crawler = $this->request('GET', 'ucp.php'); + $this->assertContains($this->lang('LOGIN_EXPLAIN_UCP'), $crawler->filter('html')->text()); + + $form = $crawler->selectButton($this->lang('LOGIN'))->form(); + $crawler = $this->client->submit($form, array('username' => $username, 'password' => $username)); + $this->assert_response_success(); + $this->assertContains($this->lang('LOGIN_REDIRECT'), $crawler->filter('html')->text()); + + $cookies = $this->cookieJar->all(); + + // The session id is stored in a cookie that ends with _sid - we assume there is only one such cookie + foreach ($cookies as $cookie); + { + if (substr($cookie->getName(), -4) == '_sid') + { + $this->sid = $cookie->getValue(); + } + } + } + + protected function add_lang($lang_file) + { + if (is_array($lang_file)) + { + foreach ($lang_file as $file) + { + $this->add_lang($file); + } + } + + $lang_path = __DIR__ . "/../../phpBB/language/en/$lang_file.php"; + + $lang = array(); + + if (file_exists($lang_path)) + { + include($lang_path); + } + + $this->lang = array_merge($this->lang, $lang); + } + + protected function lang() + { + $args = func_get_args(); + $key = $args[0]; + + if (empty($this->lang[$key])) + { + throw new RuntimeException('Language key "' . $key . '" could not be found.'); + } + + $args[0] = $this->lang[$key]; + + return call_user_func_array('sprintf', $args); + } + + /** + * Heuristic function to check that the response is success. + * + * When php decides to die with a fatal error, it still sends 200 OK + * status code. This assertion tries to catch that. + * + * @return null + */ + public function assert_response_success() + { + $this->assertEquals(200, $this->client->getResponse()->getStatus()); + $content = $this->client->getResponse()->getContent(); + $this->assertNotContains('Fatal error:', $content); + } } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index b46c36efaa..29adfc6817 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -58,9 +58,19 @@ class phpbb_test_case_helpers )); } - if (file_exists(dirname(__FILE__) . '/../test_config.php')) + if (isset($_SERVER['PHPBB_TEST_CONFIG'])) { - include(dirname(__FILE__) . '/../test_config.php'); + // Could be an absolute path + $test_config = $_SERVER['PHPBB_TEST_CONFIG']; + } + else + { + $test_config = dirname(__FILE__) . '/../test_config.php'; + } + + if (file_exists($test_config)) + { + include($test_config); $config = array_merge($config, array( 'dbms' => $dbms, @@ -69,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)) @@ -85,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'] : '', )); } diff --git a/tests/text_processing/censor_text_test.php b/tests/text_processing/censor_text_test.php index 8fcdb7ef85..f0e13638a5 100644 --- a/tests/text_processing/censor_text_test.php +++ b/tests/text_processing/censor_text_test.php @@ -9,7 +9,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../mock_user.php'; +require_once dirname(__FILE__) . '/../mock/user.php'; require_once dirname(__FILE__) . '/../mock/cache.php'; class phpbb_text_processing_censor_text_test extends phpbb_test_case diff --git a/tests/text_processing/make_clickable_test.php b/tests/text_processing/make_clickable_test.php index 8697907311..db0812319d 100644 --- a/tests/text_processing/make_clickable_test.php +++ b/tests/text_processing/make_clickable_test.php @@ -12,7 +12,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; class phpbb_text_processing_make_clickable_test extends phpbb_test_case { - public static function make_clickable_data() + static public function make_clickable_data() { // value => whether it should work $prefix_texts = array( diff --git a/tests/utf/utf8_clean_string_test.php b/tests/utf/utf8_clean_string_test.php index 70bd549d5b..5ebf6409af 100644 --- a/tests/utf/utf8_clean_string_test.php +++ b/tests/utf/utf8_clean_string_test.php @@ -11,7 +11,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; class phpbb_utf_utf8_clean_string_test extends phpbb_test_case { - public static function cleanable_strings() + static public function cleanable_strings() { return array( array('MiXed CaSe', 'mixed case', 'Checking case folding'), |