diff options
48 files changed, 2432 insertions, 1 deletions
diff --git a/code_sniffer/phpbb/Sniffs/Commenting/FileCommentSniff.php b/code_sniffer/phpbb/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 0000000000..e63c3f65fd --- /dev/null +++ b/code_sniffer/phpbb/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,210 @@ +<?php +/** +* +* @package code_sniffer +* @version $Id: $ +* @copyright (c) 2007 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* Checks that each source file contains the standard header. +* +* Based on Coding Guidelines 1.ii File Header. +* +* @package code_sniffer +* @author Manuel Pichler <mapi@phpundercontrol.org> +*/ +class phpbb_Sniffs_Commenting_FileCommentSniff implements PHP_CodeSniffer_Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array(T_OPEN_TAG); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + // We are only interested in the first file comment. + if ($stackPtr !== 0) + { + if ($phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1) !== false) + { + return; + } + } + + // Fetch next non whitespace token + $tokens = $phpcsFile->getTokens(); + $start = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + + // Skip empty files + if ($tokens[$start]['code'] === T_CLOSE_TAG) + { + return; + } + // Mark as error if this is not a doc comment + else if ($start === false || $tokens[$start]['code'] !== T_DOC_COMMENT) + { + $phpcsFile->addError('Missing required file doc comment.', $stackPtr); + return; + } + + // Find comment end token + $end = $phpcsFile->findNext(T_DOC_COMMENT, $start + 1, null, true) - 1; + + // If there is no end, skip processing here + if ($end === false) + { + return; + } + + // List of found comment tags + $tags = array(); + + // check comment lines without the first(/**) an last(*/) line + for ($i = $start + 1, $c = ($end - $start); $i <= $c; ++$i) + { + $line = $tokens[$i]['content']; + + // Check that each line starts with a '*' + if (substr($line, 0, 1) !== '*') + { + $message = 'The file doc comment should not be idented.'; + $phpcsFile->addWarning($message, $i); + } + else if (preg_match('/^\*\s+@([\w]+)\s+(.*)$/', $line, $match) !== 0) + { + $tags[$match[1]] = array($match[2], $i); + } + } + + // Check that the first and last line is empty + if (trim($tokens[$start + 1]['content']) !== '*') + { + $message = 'The first file comment line should be empty.'; + $phpcsFile->addWarning($message, ($start + 1)); + } + if (trim($tokens[$end - $start]['content']) !== '*') + { + $message = 'The last file comment line should be empty.'; + $phpcsFile->addWarning($message, ($end - $start)); + } + + $this->processPackage($phpcsFile, $start, $tags); + $this->processVersion($phpcsFile, $start, $tags); + $this->processCopyright($phpcsFile, $start, $tags); + $this->processLicense($phpcsFile, $start, $tags); + + //print_r($tags); + } + + /** + * Checks that the tags array contains a valid package tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return void + */ + protected function processPackage(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + if (!isset($tags['package'])) + { + $message = 'Missing require @package tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (preg_match('/^([\w]+)$/', $tags['package'][0]) === 0) + { + $message = 'Invalid content found for @package tag.'; + $phpcsFile->addWarning($message, $tags['package'][1]); + } + } + + /** + * Checks that the tags array contains a valid version tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return void + */ + protected function processVersion(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + if (!isset($tags['version'])) + { + $message = 'Missing require @version tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (preg_match('/^\$Id:[^\$]+\$$/', $tags['version'][0]) === 0) + { + $message = 'Invalid content found for @version tag, use "$Id: $".'; + $phpcsFile->addError($message, $tags['version'][1]); + } + } + + /** + * Checks that the tags array contains a valid copyright tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return void + */ + protected function processCopyright(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + if (!isset($tags['copyright'])) + { + $message = 'Missing require @copyright tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (preg_match('/^\(c\) 2[0-9]{3} phpBB Group\s*$/', $tags['copyright'][0]) === 0) + { + $message = 'Invalid content found for @copyright tag, use "(c) <year> phpBB Group".'; + $phpcsFile->addError($message, $tags['copyright'][1]); + } + } + + /** + * Checks that the tags array contains a valid license tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return void + */ + protected function processLicense(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + $license = 'http://opensource.org/licenses/gpl-license.php GNU Public License'; + + if (!isset($tags['license'])) + { + $message = 'Missing require @license tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (trim($tags['license'][0]) !== $license) + { + $message = 'Invalid content found for @license tag, use ' + . '"' . $license . '".'; + $phpcsFile->addError($message, $tags['license'][1]); + } + } +}
\ No newline at end of file diff --git a/code_sniffer/phpbb/Tests/Commenting/FileCommentUnitTest.inc b/code_sniffer/phpbb/Tests/Commenting/FileCommentUnitTest.inc new file mode 100644 index 0000000000..0ace1c1bda --- /dev/null +++ b/code_sniffer/phpbb/Tests/Commenting/FileCommentUnitTest.inc @@ -0,0 +1,19 @@ +<?php +/** +* +* @package code_sniffer³ +* @version $Id: $ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php BSD License + * +*/ +?> +<?php +/** +* Broken but not first file doc comment. +* +* @version @package_version@ +* @license http://www.opensource.org/licenses/bsd-license.php BSD License +* @copyright (c) 2007 phpBB Group +* +*/ diff --git a/code_sniffer/phpbb/Tests/Commenting/FileCommentUnitTest.php b/code_sniffer/phpbb/Tests/Commenting/FileCommentUnitTest.php new file mode 100644 index 0000000000..849a7fb9a0 --- /dev/null +++ b/code_sniffer/phpbb/Tests/Commenting/FileCommentUnitTest.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package code_sniffer +* @version $Id: $ +* @copyright (c) 2007 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* Unit test class for the EmptyStatement sniff. +* +* @package code_sniffer +* @author Manuel Pichler <mapi@phpundercontrol.org> +*/ +class phpbb_Tests_Commenting_FileCommentUnitTest extends AbstractSniffUnitTest +{ + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array(int => int) + */ + public function getErrorList() + { + return array( + 7 => 1 // BSD License error :) + ); + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array(int => int) + */ + public function getWarningList() + { + return array( + 4 => 1, + 8 => 1 + ); + }//end getWarningList() +}
\ No newline at end of file diff --git a/code_sniffer/phpbb/build.xml b/code_sniffer/phpbb/build.xml new file mode 100644 index 0000000000..b6d3bf6451 --- /dev/null +++ b/code_sniffer/phpbb/build.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="code_sniffer" basedir="." default="install"> + + <property name="working.dir" value="${basedir}" /> + <property name="target.dir" value="/usr/share/php/PHP/CodeSniffer/Standards" /> + + <!-- + Install phpbb sniff + --> + <target name="install"> + <delete dir="${target.dir}/phpbb" /> + <mkdir dir="${target.dir}/phpbb"/> + + <copy todir="${target.dir}/phpbb"> + <fileset file="${working.dir}/phpbbCodingStandard.php" /> + </copy> + <copy todir="${target.dir}/phpbb/Sniffs"> + <fileset dir="${working.dir}/Sniffs" /> + </copy> + + </target> + +</project> diff --git a/code_sniffer/phpbb/phpbbCodingStandard.php b/code_sniffer/phpbb/phpbbCodingStandard.php new file mode 100644 index 0000000000..be51b54b40 --- /dev/null +++ b/code_sniffer/phpbb/phpbbCodingStandard.php @@ -0,0 +1,43 @@ +<?php +/** +* +* @package code_sniffer +* @version $Id: $ +* @copyright (c) 2007 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** + * @ignore + */ +if (class_exists('PHP_CodeSniffer_Standards_CodingStandard', true) === false) { + throw new PHP_CodeSniffer_Exception( + 'Class PHP_CodeSniffer_Standards_CodingStandard not found' + ); +} + +/** + * Primary class for the phpbb coding standard. + * + * @package code_sniffer + */ +class PHP_CodeSniffer_Standards_phpbb_phpbbCodingStandard extends PHP_CodeSniffer_Standards_CodingStandard +{ + /** + * Return a list of external sniffs to include with this standard. + * + * External locations can be single sniffs, a whole directory of sniffs, or + * an entire coding standard. Locations start with the standard name. For + * example: + * PEAR => include all sniffs in this standard + * PEAR/Sniffs/Files => include all sniffs in this dir + * PEAR/Sniffs/Files/LineLengthSniff => include this single sniff + * + * @return array + */ + public function getIncludedSniffs() + { + return array(); + } +}
\ No newline at end of file diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 0515d801f2..4fb7b0d8f7 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1200,6 +1200,7 @@ function get_schema_struct() 'PRIMARY_KEY' => 'log_id', 'KEYS' => array( 'log_type' => array('INDEX', 'log_type'), + 'log_time' => array('INDEX', 'log_time'), 'forum_id' => array('INDEX', 'forum_id'), 'topic_id' => array('INDEX', 'topic_id'), 'reportee_id' => array('INDEX', 'reportee_id'), diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index 57230339e8..85da1dfa47 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -688,6 +688,7 @@ function get_schema_struct() 'PRIMARY_KEY' => 'log_id', 'KEYS' => array( 'log_type' => array('INDEX', 'log_type'), + 'log_time' => array('INDEX', 'log_time'), 'forum_id' => array('INDEX', 'forum_id'), 'topic_id' => array('INDEX', 'topic_id'), 'reportee_id' => array('INDEX', 'reportee_id'), diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index 85f86781de..ab622e8fde 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -529,6 +529,7 @@ CREATE TABLE phpbb_log ( ALTER TABLE phpbb_log ADD PRIMARY KEY (log_id);; CREATE INDEX phpbb_log_log_type ON phpbb_log(log_type);; +CREATE INDEX phpbb_log_log_time ON phpbb_log(log_time);; CREATE INDEX phpbb_log_forum_id ON phpbb_log(forum_id);; CREATE INDEX phpbb_log_topic_id ON phpbb_log(topic_id);; CREATE INDEX phpbb_log_reportee_id ON phpbb_log(reportee_id);; diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index 0827b14cc2..068373c9a1 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -636,6 +636,9 @@ GO CREATE INDEX [log_type] ON [phpbb_log]([log_type]) ON [PRIMARY] GO +CREATE INDEX [log_time] ON [phpbb_log]([log_time]) ON [PRIMARY] +GO + CREATE INDEX [forum_id] ON [phpbb_log]([forum_id]) ON [PRIMARY] GO diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 19b1b4f0f7..813cf8613f 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -362,6 +362,7 @@ CREATE TABLE phpbb_log ( log_data mediumblob NOT NULL, PRIMARY KEY (log_id), KEY log_type (log_type), + KEY log_time (log_time), KEY forum_id (forum_id), KEY topic_id (topic_id), KEY reportee_id (reportee_id), diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 3b70630a9e..97369d2bf7 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -362,6 +362,7 @@ CREATE TABLE phpbb_log ( log_data mediumtext NOT NULL, PRIMARY KEY (log_id), KEY log_type (log_type), + KEY log_time (log_time), KEY forum_id (forum_id), KEY topic_id (topic_id), KEY reportee_id (reportee_id), diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index d577fce46c..7be7cd0756 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -715,6 +715,8 @@ CREATE TABLE phpbb_log ( CREATE INDEX phpbb_log_log_type ON phpbb_log (log_type) / +CREATE INDEX phpbb_log_log_time ON phpbb_log (log_time) +/ CREATE INDEX phpbb_log_forum_id ON phpbb_log (forum_id) / CREATE INDEX phpbb_log_topic_id ON phpbb_log (topic_id) diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index 50b3979adb..9cdf35024b 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -519,6 +519,7 @@ CREATE TABLE phpbb_log ( ); CREATE INDEX phpbb_log_log_type ON phpbb_log (log_type); +CREATE INDEX phpbb_log_log_time ON phpbb_log (log_time); CREATE INDEX phpbb_log_forum_id ON phpbb_log (forum_id); CREATE INDEX phpbb_log_topic_id ON phpbb_log (topic_id); CREATE INDEX phpbb_log_reportee_id ON phpbb_log (reportee_id); diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index 7ee821d395..34b4b05478 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -352,6 +352,7 @@ CREATE TABLE phpbb_log ( ); CREATE INDEX phpbb_log_log_type ON phpbb_log (log_type); +CREATE INDEX phpbb_log_log_time ON phpbb_log (log_time); CREATE INDEX phpbb_log_forum_id ON phpbb_log (forum_id); CREATE INDEX phpbb_log_topic_id ON phpbb_log (topic_id); CREATE INDEX phpbb_log_reportee_id ON phpbb_log (reportee_id); diff --git a/phpBB/styles/prosilver/template/ucp_register.html b/phpBB/styles/prosilver/template/ucp_register.html index 0c632f5c69..e63abaec05 100644 --- a/phpBB/styles/prosilver/template/ucp_register.html +++ b/phpBB/styles/prosilver/template/ucp_register.html @@ -48,7 +48,7 @@ </dl> <dl> <dt><label for="password_confirm">{L_CONFIRM_PASSWORD}:</label></dt> - <dd><input type="password" tabindex="5" name="password_confirm" id="password_confirm" size="25" value="{PASSWORD_CONFIRM}" class="inputbox autowidth" title="{L_CONFIRM_PASSWORD}" /></dd> + <dd><input type="password" tabindex="5" name="password_confirm" id="password_confirm" size="25" value="{PASSWORD_CONFIRM}" class="inputbox autowidth" title="{L_CONFIRM_PASSWORD}" /></dd> </dl> <hr /> diff --git a/tests/all_tests.php b/tests/all_tests.php new file mode 100644 index 0000000000..f22ee5dc49 --- /dev/null +++ b/tests/all_tests.php @@ -0,0 +1,54 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +if (!defined('PHPUnit_MAIN_METHOD')) +{ + define('PHPUnit_MAIN_METHOD', 'phpbb_all_tests::main'); +} + +require_once 'test_framework/framework.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +require_once 'utf/all_tests.php'; +require_once 'request/all_tests.php'; +require_once 'security/all_tests.php'; +#require_once 'template/all_tests.php'; +#require_once 'bbcode/all_tests.php'; +require_once 'text_processing/all_tests.php'; + +// exclude the test directory from code coverage reports +PHPUnit_Util_Filter::addDirectoryToFilter('./'); + +class phpbb_all_tests +{ + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + $suite = new PHPUnit_Framework_TestSuite('phpBB'); + + $suite->addTest(phpbb_utf_all_tests::suite()); + $suite->addTest(phpbb_request_all_tests::suite()); + $suite->addTest(phpbb_security_all_tests::suite()); +# $suite->addTest(phpbb_template_all_tests::suite()); +# $suite->addTest(phpbb_bbcode_all_tests::suite()); + $suite->addTest(phpbb_text_processing_all_tests::suite()); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'phpbb_all_tests::main') +{ + phpbb_all_tests::main(); +} diff --git a/tests/bbcode/all_tests.php b/tests/bbcode/all_tests.php new file mode 100644 index 0000000000..f4200fd0a9 --- /dev/null +++ b/tests/bbcode/all_tests.php @@ -0,0 +1,44 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +define('IN_PHPBB', true); + +if (!defined('PHPUnit_MAIN_METHOD')) +{ + define('PHPUnit_MAIN_METHOD', 'phpbb_bbcode_all_tests::main'); +} + +require_once 'test_framework/framework.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +require_once 'bbcode/parser_test.php'; + +class phpbb_bbcode_all_tests +{ + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + $suite = new PHPUnit_Framework_TestSuite('phpBB Formatted Text / BBCode'); + + $suite->addTestSuite('phpbb_bbcode_parser_test'); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'phpbb_bbcode_all_tests::main') +{ + phpbb_bbcode_all_tests::main(); +} +?>
\ No newline at end of file diff --git a/tests/bbcode/parser_test.php b/tests/bbcode/parser_test.php new file mode 100644 index 0000000000..729fe93fc2 --- /dev/null +++ b/tests/bbcode/parser_test.php @@ -0,0 +1,31 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +define('IN_PHPBB', true); + +require_once 'test_framework/framework.php'; +require_once '../phpBB/includes/bbcode/bbcode_parser_base.php'; +require_once '../phpBB/includes/bbcode/bbcode_parser.php'; + +class phpbb_bbcode_parser_test extends PHPUnit_Framework_TestCase +{ + public function test_both_passes() + { + $parser = new phpbb_bbcode_parser(); + + $result = $parser->first_pass('[i]Italic [u]underlined text[/u][/i]'); + $result = $parser->second_pass($result); + + $expected = '<span style="font-style: italic">Italic <span style="text-decoration: underline">underlined text</span></span>'; + + $this->assertEquals($expected, $result, 'Simple nested BBCode first+second pass'); + } +} +?>
\ No newline at end of file diff --git a/tests/request/all_tests.php b/tests/request/all_tests.php new file mode 100644 index 0000000000..dc5d26417f --- /dev/null +++ b/tests/request/all_tests.php @@ -0,0 +1,41 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +if (!defined('PHPUnit_MAIN_METHOD')) +{ + define('PHPUnit_MAIN_METHOD', 'phpbb_request_all_tests::main'); +} + +require_once 'test_framework/framework.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +require_once 'request/request_var.php'; + +class phpbb_request_all_tests +{ + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + $suite = new PHPUnit_Framework_TestSuite('phpBB Request Parameter Handling'); + + $suite->addTestSuite('phpbb_request_request_var_test'); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'phpbb_request_all_tests::main') +{ + phpbb_request_all_tests::main(); +} diff --git a/tests/request/request_class.php b/tests/request/request_class.php new file mode 100644 index 0000000000..e8c2154bab --- /dev/null +++ b/tests/request/request_class.php @@ -0,0 +1,74 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +define('IN_PHPBB', true); + +require_once 'test_framework/framework.php'; + +require_once '../phpBB/includes/functions.php'; + +class phpbb_request_request_class_test extends phpbb_test_case +{ + protected function setUp() + { + $_POST['test'] = 1; + $_GET['test'] = 2; + $_COOKIE['test'] = 3; + $_REQUEST['test'] = 3; + + // reread data from super globals + request::reset(); + } + + public function test_toggle_super_globals() + { + // toggle super globals + request::disable_super_globals(); + request::enable_super_globals(); + + $this->assertEquals(1, $_POST['test'], 'Checking $_POST toggling via request::dis/enable_super_globals'); + $this->assertEquals(2, $_GET['test'], 'Checking $_GET toggling via request::dis/enable_super_globals'); + $this->assertEquals(3, $_COOKIE['test'], 'Checking $_COOKIE toggling via request::dis/enable_super_globals'); + $this->assertEquals(3, $_REQUEST['test'], 'Checking $_REQUEST toggling via request::dis/enable_super_globals'); + + $_POST['x'] = 2; + $this->assertEquals($_POST, $GLOBALS['_POST'], 'Checking whether $_POST can still be accessed via $GLOBALS[\'_POST\']'); + } + + /** + * Checks that directly accessing $_POST will trigger + * an error. + */ + public function test_disable_post_super_global() + { + request::disable_super_globals(); + + $this->setExpectedTriggerError(E_USER_ERROR); + $_POST['test'] = 3; + } + + public function test_is_set_post() + { + $_GET['unset'] = ''; + request::reset(); + + $this->assertTrue(request::is_set_post('test')); + $this->assertFalse(request::is_set_post('unset')); + } + + /** + * Makes sure super globals work properly after these tests + */ + protected function tearDown() + { + request::enable_super_globals(); + request::reset(); + } +}
\ No newline at end of file diff --git a/tests/request/request_var.php b/tests/request/request_var.php new file mode 100644 index 0000000000..c0f8a22d95 --- /dev/null +++ b/tests/request/request_var.php @@ -0,0 +1,264 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once 'test_framework/framework.php'; +require_once '../phpBB/includes/functions.php'; + +class phpbb_request_request_var_test extends phpbb_test_case +{ + /** + * @dataProvider request_variables + */ + public function test_post($variable_value, $default, $multibyte, $expected) + { + $variable_name = 'name'; + $this->unset_variables($variable_name); + + $_POST[$variable_name] = $variable_value; + $_REQUEST[$variable_name] = $variable_value; + + $result = request_var($variable_name, $default, $multibyte); + + $label = 'Requesting POST variable, converting from ' . gettype($variable_value) . ' to ' . gettype($default) . (($multibyte) ? ' multibyte' : ''); + $this->assertEquals($expected, $result, $label); + } + + /** + * @dataProvider request_variables + */ + public function test_get($variable_value, $default, $multibyte, $expected) + { + $variable_name = 'name'; + $this->unset_variables($variable_name); + + $_GET[$variable_name] = $variable_value; + $_REQUEST[$variable_name] = $variable_value; + + $result = request_var($variable_name, $default, $multibyte); + + $label = 'Requesting GET variable, converting from ' . gettype($variable_value) . ' to ' . gettype($default) . (($multibyte) ? ' multibyte' : ''); + $this->assertEquals($expected, $result, $label); + } + + /** + * @dataProvider request_variables + */ + public function test_cookie($variable_value, $default, $multibyte, $expected) + { + $variable_name = 'name'; + $this->unset_variables($variable_name); + + $_GET[$variable_name] = false; + $_POST[$variable_name] = false; + $_REQUEST[$variable_name] = false; + $_COOKIE[$variable_name] = $variable_value; + + $result = request_var($variable_name, $default, $multibyte, true); + + $label = 'Requesting COOKIE variable, converting from ' . gettype($variable_value) . ' to ' . gettype($default) . (($multibyte) ? ' multibyte' : ''); + $this->assertEquals($expected, $result, $label); + } + + /** + * Helper for unsetting globals + */ + private function unset_variables($var) + { + unset($_GET[$var], $_POST[$var], $_REQUEST[$var], $_COOKIE[$var]); + } + + /** + * @dataProvider deep_access + * Only possible with 3.1.x (later) + public function test_deep_multi_dim_array_access($path, $default, $expected) + { + $this->unset_variables('var'); + + $_REQUEST['var'] = array( + 0 => array( + 'b' => array( + true => array( + 5 => 'c', + 6 => 'd', + ), + ), + ), + 2 => array( + 3 => array( + false => 5, + ), + ), + ); + + $result = request_var($path, $default); + $this->assertEquals($expected, $result, 'Testing deep access to multidimensional input arrays: ' . $path); + } + + public static function deep_access() + { + return array( + // array(path, default, expected result) + array(array('var', 0, 'b', true, 5), '', 'c'), + array(array('var', 0, 'b', true, 6), '', 'd'), + array(array('var', 2, 3, false), 0, 5), + array(array('var', 0, 'b', true), array(0 => ''), array(5 => 'c', 6 => 'd')), + ); + } +*/ + public static function request_variables() + { + return array( + // strings + array('abc', '', false, 'abc'), + array(' some spaces ', '', true, 'some spaces'), + array("\r\rsome\rcarriage\r\rreturns\r", '', true, "some\ncarriage\n\nreturns"), + array("\n\nsome\ncarriage\n\nreturns\n", '', true, "some\ncarriage\n\nreturns"), + array("\r\n\r\nsome\r\ncarriage\r\n\r\nreturns\r\n", '', true, "some\ncarriage\n\nreturns"), + array("we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters", '', true, "we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters"), + array("we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters", '', false, "we??rd???ch??r??acters"), + array("Some <html> \"entities\" like &", '', true, "Some <html> "entities" like &"), + + // integers + array('1234', 0, false, 1234), + array('abc', 12, false, 0), + array('324abc', 0, false, 324), + + // string to array + array('123', array(0), false, array()), + array('123', array(''), false, array()), + + // 1 dimensional arrays + array( + // input: + array('123', 'abc'), + // default: + array(''), + false, + // expected: + array('123', 'abc') + ), + array( + // input: + array('123', 'abc'), + // default: + array(999), + false, + // expected: + array(123, 0) + ), + array( + // input: + array('xyz' => '123', 'abc' => 'abc'), + // default: + array('' => ''), + false, + // expected: + array('xyz' => '123', 'abc' => 'abc') + ), + array( + // input: + array('xyz' => '123', 'abc' => 'abc'), + // default: + array('' => 0), + false, + // expected: + array('xyz' => 123, 'abc' => 0) + ), + + // 2 dimensional arrays + array( + // input: + '', + // default: + array(array(0)), + false, + // expected: + array() + ), + array( + // input: + array( + 'xyz' => array('123', 'def'), + 'abc' => 'abc' + ), + // default: + array('' => array('')), + false, + // expected: + array( + 'xyz' => array('123', 'def'), + 'abc' => array() + ) + ), + array( + // input: + array( + 'xyz' => array('123', 'def'), + 'abc' => 'abc' + ), + // default: + array('' => array(0)), + false, + // expected: + array( + 'xyz' => array(123, 0), + 'abc' => array() + ) + ), + /* 3-dimensional (not supported atm! + array( + // input: + array( + 0 => array(0 => array(3, '4', 'ab'), 1 => array()), + 1 => array(array(3, 4)), + ), + // default: + array(0 => array(0 => array(0))), + false, + // expected: + array( + 0 => array(0 => array(3, 4, 0), 1 => array()), + 1 => array(array(3, 4)) + ) + ), + array( + // input: + array( + 'ü' => array(array('c' => 'd')), + 'ä' => array(4 => array('a' => 2, 'ö' => 3)), + ), + // default: + array('' => array(0 => array('' => 0))), + false, + // expected: + array( + '??' => array(4 => array('a' => 2, '??' => 3)), + ) + ), + array( + // input: + array( + 'ü' => array(array('c' => 'd')), + 'ä' => array(4 => array('a' => 2, 'ö' => 3)), + ), + // default: + array('' => array(0 => array('' => 0))), + true, + // expected: + array( + 'ü' => array(array('c' => 0)), + 'ä' => array(4 => array('a' => 2, 'ö' => 3)), + ) + ), + */ + ); + } + +} diff --git a/tests/security/all_tests.php b/tests/security/all_tests.php new file mode 100644 index 0000000000..bff3ca82ab --- /dev/null +++ b/tests/security/all_tests.php @@ -0,0 +1,88 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +if (!defined('PHPUnit_MAIN_METHOD')) +{ + define('PHPUnit_MAIN_METHOD', 'phpbb_security_all_tests::main'); +} + +require_once 'test_framework/framework.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +require_once 'security/extract_current_page.php'; +require_once 'security/redirect.php'; + +class phpbb_security_all_tests extends PHPUnit_Framework_TestSuite +{ + /** + * Set up the required user object and server variables for the suites + */ + protected function setUp() + { + global $user, $phpbb_root_path; + + // Put this into a global function being run by every test to init a proper user session + $_SERVER['HTTP_HOST'] = 'localhost'; + $_SERVER['SERVER_NAME'] = 'localhost'; + $_SERVER['SERVER_ADDR'] = '127.0.0.1'; + $_SERVER['SERVER_PORT'] = 80; + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + $_SERVER['QUERY_STRING'] = ''; + $_SERVER['REQUEST_URI'] = '/tests/'; + $_SERVER['SCRIPT_NAME'] = '/tests/index.php'; + $_SERVER['PHP_SELF'] = '/tests/index.php'; + $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14'; + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3'; + +/* + [HTTP_ACCEPT_ENCODING] => gzip,deflate + [HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.7 + DOCUMENT_ROOT] => /var/www/ + [SCRIPT_FILENAME] => /var/www/tests/index.php +*/ + + // Set no user and trick a bit to circumvent errors + $user = new user(); + $user->lang = true; + $user->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; + $user->referer = (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; + $user->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : ''; + $user->host = (!empty($_SERVER['HTTP_HOST'])) ? (string) strtolower($_SERVER['HTTP_HOST']) : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); + $user->page = session::extract_current_page($phpbb_root_path); + } + + protected function tearDown() + { + global $user; + $user = NULL; + } + + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + // I bet there is a better method calling this... :) + $suite = new phpbb_security_all_tests('phpBB Security Fixes'); + + $suite->addTestSuite('phpbb_security_extract_current_page_test'); + $suite->addTestSuite('phpbb_security_redirect_test'); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'phpbb_security_all_tests::main') +{ + phpbb_security_all_tests::main(); +} +?>
\ No newline at end of file diff --git a/tests/security/extract_current_page.php b/tests/security/extract_current_page.php new file mode 100644 index 0000000000..2b61ac7062 --- /dev/null +++ b/tests/security/extract_current_page.php @@ -0,0 +1,53 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once 'test_framework/framework.php'; + +require_once '../phpBB/includes/functions.php'; +require_once '../phpBB/includes/session.php'; + +class phpbb_security_extract_current_page_test extends phpbb_test_case +{ + public static 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'), + array('http://localhost/phpBB/index.php', 'mark=forums&x=%22%3E%3Cscript%3Ealert(/XSS/);%3C/script%3E', 'mark=forums&x=%22%3E%3Cscript%3Ealert(/XSS/);%3C/script%3E'), + ); + } + + /** + * @dataProvider security_variables + */ + public function test_query_string_php_self($url, $query_string, $expected) + { + $_SERVER['PHP_SELF'] = $url; + $_SERVER['QUERY_STRING'] = $query_string; + + $result = session::extract_current_page('./'); + + $label = 'Running extract_current_page on ' . $query_string . ' with PHP_SELF filled.'; + $this->assertEquals($expected, $result['query_string'], $label); + } + + /** + * @dataProvider security_variables + */ + public function test_query_string_request_uri($url, $query_string, $expected) + { + $_SERVER['REQUEST_URI'] = $url . '?' . $query_string; + $_SERVER['QUERY_STRING'] = $query_string; + + $result = session::extract_current_page('./'); + + $label = 'Running extract_current_page on ' . $query_string . ' with REQUEST_URI filled.'; + $this->assertEquals($expected, $result['query_string'], $label); + } +} diff --git a/tests/security/redirect.php b/tests/security/redirect.php new file mode 100644 index 0000000000..1d565ec7e3 --- /dev/null +++ b/tests/security/redirect.php @@ -0,0 +1,58 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once 'test_framework/framework.php'; + +require_once '../phpBB/includes/functions.php'; +require_once '../phpBB/includes/session.php'; + +class phpbb_security_redirect_test extends phpbb_test_case +{ + public static function provider() + { + // array(Input -> redirect(), expected triggered error (else false), expected returned result url (else false)) + return array( + array('data://x', false, 'http://localhost/phpBB'), + array('bad://localhost/phpBB/index.php', 'Tried to redirect to potentially insecure url.', false), + array('http://www.otherdomain.com/somescript.php', false, 'http://localhost/phpBB'), + array("http://localhost/phpBB/memberlist.php\n\rConnection: close", 'Tried to redirect to potentially insecure url.', false), + array('javascript:test', false, 'http://localhost/phpBB/../tests/javascript:test'), + array('http://localhost/phpBB/index.php;url=', 'Tried to redirect to potentially insecure url.', false), + ); + } + + protected function setUp() + { + $GLOBALS['config'] = array( + 'force_server_vars' => '0', + ); + } + + /** + * @dataProvider provider + */ + public function test_redirect($test, $expected_error, $expected_result) + { + global $user; + + if ($expected_error !== false) + { + $this->setExpectedTriggerError(E_USER_ERROR, $expected_error); + } + + $result = redirect($test, true); + + // only verify result if we did not expect an error + if ($expected_error === false) + { + $this->assertEquals($expected_result, $result); + } + } +} diff --git a/tests/template/all_tests.php b/tests/template/all_tests.php new file mode 100644 index 0000000000..b4f6f741ca --- /dev/null +++ b/tests/template/all_tests.php @@ -0,0 +1,41 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +if (!defined('PHPUnit_MAIN_METHOD')) +{ + define('PHPUnit_MAIN_METHOD', 'phpbb_template_all_tests::main'); +} + +require_once 'test_framework/framework.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +require_once 'template/template.php'; + +class phpbb_template_all_tests +{ + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + $suite = new PHPUnit_Framework_TestSuite('phpBB Template Engine'); + + $suite->addTestSuite('phpbb_template_template_test'); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'phpbb_template_all_tests::main') +{ + phpbb_template_all_tests::main(); +}
\ No newline at end of file diff --git a/tests/template/template.php b/tests/template/template.php new file mode 100644 index 0000000000..bde1c55e9d --- /dev/null +++ b/tests/template/template.php @@ -0,0 +1,666 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once 'test_framework/framework.php'; + +require_once '../phpBB/includes/template.php'; + +class phpbb_template_template_test extends phpbb_test_case +{ + private $template; + private $template_path; + + // Keep the contents of the cache for debugging? + const PRESERVE_CACHE = false; + + private function display($handle) + { + ob_start(); + $this->assertTrue($this->template->display($handle, false)); + return self::trim_template_result(ob_get_clean()); + } + + private static function trim_template_result($result) + { + return str_replace("\n\n", "\n", implode("\n", array_map('trim', explode("\n", trim($result))))); + } + + private function setup_engine() + { + $this->template_path = dirname(__FILE__) . '/templates'; + $this->template = new template(); + $this->template->set_custom_template($this->template_path, 'tests'); + } + + protected function setUp() + { + // Test the engine can be used + $this->setup_engine(); + + if (!is_writable(dirname($this->template->cachepath))) + { + $this->markTestSkipped("Template cache directory is not writable."); + } + + foreach (glob($this->template->cachepath . '*') as $file) + { + unlink($file); + } + + $GLOBALS['config'] = array( + 'load_tplcompile' => true, + 'tpl_allow_php' => false, + ); + } + + protected function tearDown() + { + if (is_object($this->template)) + { + foreach (glob($this->template->cachepath . '*') as $file) + { + unlink($file); + } + } + } + + /** + * @todo put test data into templates/xyz.test + */ + public static function template_data() + { + return array( + /* + array( + '', // File + array(), // vars + array(), // block vars + array(), // destroy + '', // Expected result + ), + */ + array( + 'basic.html', + array(), + array(), + array(), + "pass\npass\n<!-- DUMMY var -->", + ), + array( + 'variable.html', + array('VARIABLE' => 'value'), + array(), + array(), + 'value', + ), + array( + 'if.html', + array(), + array(), + array(), + '0', + ), + array( + 'if.html', + array('S_VALUE' => true), + array(), + array(), + '1', + ), + array( + 'if.html', + array('S_VALUE' => true, 'S_OTHER_VALUE' => true), + array(), + array(), + '1', + ), + array( + 'if.html', + array('S_VALUE' => false, 'S_OTHER_VALUE' => true), + array(), + array(), + '2', + ), + array( + 'loop.html', + array(), + array(), + array(), + "noloop\nnoloop", + ), + array( + 'loop.html', + array(), + array('loop' => array(array())), + array(), + "loop\nloop", + ), + array( + 'loop.html', + array(), + array('loop' => array(array(), array()), 'loop.block' => array(array())), + array(), + "loop\nloop\nloop\nloop", + ), + array( + 'loop.html', + array(), + array('loop' => array(array(), array()), 'loop.block' => array(array()), 'block' => array(array(), array())), + array(), + "loop\nloop\nloop\nloop\n\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1", + ), + array( + 'loop_vars.html', + array(), + array('loop' => array(array('VARIABLE' => 'x'))), + array(), + "first\n0\n0\n1\nx\nset\nlast", + ), + array( + 'loop_vars.html', + array(), + array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y'))), + array(), + "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast", + ), + array( + 'loop_vars.html', + array(), + array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())), + array(), + "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast\n0\n\n1\nlast inner\ninner loop", + ), + array( + 'loop_advanced.html', + array(), + array('loop' => array(array(), array(), array(), array(), array(), array(), array())), + array(), + "101234561\n101234561\n101234561\n1234561\n1\n101\n234\n10\n561\n561", + ), + array( + 'define.html', + array(), + array('loop' => array(array(), array(), array(), array(), array(), array(), array()), 'test' => array(array()), 'test.deep' => array(array()), 'test.deep.defines' => array(array())), + array(), + "xyz\nabc\n\n00\n11\n22\n33\n44\n55\n66\n\n144\n144", + ), + array( + 'expressions.html', + array(), + array(), + array(), + trim(str_repeat("pass\n", 40)), + ), + array( + 'php.html', + array(), + array(), + array(), + '<!-- echo "test"; -->', + ), + array( + 'include.html', + array('VARIABLE' => 'value'), + array(), + array(), + 'value', + ), + array( + 'loop_vars.html', + array(), + array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())), + array('loop'), + '', + ), + array( + 'loop_vars.html', + array(), + array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())), + array('loop.inner'), + "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast", + ), + array( + 'loop_expressions.html', + array(), + array('loop' => array(array(), array(), array(), array(), array(), array(), array(), array(), array(), array(), array(), array())), + array(), + "on\non\non\non\noff\noff\noff\noff\non\non\non\non\n\noff\noff\noff\non\non\non\noff\noff\noff\non\non\non", + ), + array( + 'lang.html', + array(), + array(), + array(), + "{ VARIABLE }\n{ VARIABLE }", + ), + array( + 'lang.html', + array('L_VARIABLE' => "Value'"), + array(), + array(), + "Value'\nValue\'", + ), + array( + 'lang.html', + array('LA_VARIABLE' => "Value'"), + array(), + array(), + "{ VARIABLE }\nValue'", + ), + ); + } + + public function test_missing_file() + { + $filename = 'file_not_found.html'; + + $this->template->set_filenames(array('test' => $filename)); + $this->assertFileNotExists($this->template_path . '/' . $filename, 'Testing missing file, file cannot exist'); + + $expecting = sprintf('template->_tpl_load_file(): File %s does not exist or is empty', realpath($this->template_path) . '/' . $filename); + $this->setExpectedTriggerError(E_USER_ERROR, $expecting); + + $this->display('test'); + } + + public function test_empty_file() + { + $expecting = 'template->set_filenames: Empty filename specified for test'; + + $this->setExpectedTriggerError(E_USER_ERROR, $expecting); + $this->template->set_filenames(array('test' => '')); + } + + public function test_invalid_handle() + { + $expecting = 'template->_tpl_load(): No file specified for handle test'; + $this->setExpectedTriggerError(E_USER_ERROR, $expecting); + + $this->display('test'); + } + + private function run_template($file, array $vars, array $block_vars, array $destroy, $expected, $cache_file) + { + $this->template->set_filenames(array('test' => $file)); + $this->template->assign_vars($vars); + + foreach ($block_vars as $block => $loops) + { + foreach ($loops as $_vars) + { + $this->template->assign_block_vars($block, $_vars); + } + } + + foreach ($destroy as $block) + { + $this->template->destroy_block_vars($block); + } + + try + { + $this->assertEquals($expected, $this->display('test'), "Testing $file"); + $this->assertFileExists($cache_file); + } + catch (ErrorException $e) + { + if (file_exists($cache_file)) + { + copy($cache_file, str_replace('ctpl_', 'tests_ctpl_', $cache_file)); + } + + throw $e; + } + + // For debugging + if (self::PRESERVE_CACHE) + { + copy($cache_file, str_replace('ctpl_', 'tests_ctpl_', $cache_file)); + } + } + + /** + * @dataProvider template_data + */ + public function test_template($file, array $vars, array $block_vars, array $destroy, $expected) + { + global $phpEx; + $cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.' . $phpEx; + + $this->assertFileNotExists($cache_file); + + $this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file); + + // Reset the engine state + $this->setup_engine(); + + $this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file); + } + + /** + * @dataProvider template_data + public function test_assign_display($file, array $vars, array $block_vars, array $destroy, $expected) + { + $this->template->set_filenames(array( + 'test' => $file, + 'container' => 'variable.html', + )); + $this->template->assign_vars($vars); + + foreach ($block_vars as $block => $loops) + { + foreach ($loops as $_vars) + { + $this->template->assign_block_vars($block, $_vars); + } + } + + foreach ($destroy as $block) + { + $this->template->destroy_block_vars($block); + } + + $this->assertEquals($expected, self::trim_template_result($this->template->assign_display('test')), "Testing assign_display($file)"); + + $this->template->assign_display('test', 'VARIABLE', false); + $this->assertEquals($expected, $this->display('container'), "Testing assign_display($file)"); + } + + public function test_php() + { + global $phpEx; + + $GLOBALS['config']['tpl_allow_php'] = true; + + $cache_file = $this->template->cachepath . 'php.html.' . $phpEx; + + $this->assertFileNotExists($cache_file); + + $this->run_template('php.html', array(), array(), array(), 'test', $cache_file); + + $GLOBALS['config']['tpl_allow_php'] = false; + } +*/ +/* + public function test_includephp() + { + phpbb::$config['tpl_allow_php'] = true; + + $cache_file = $this->template->cachepath . 'includephp.html.' . PHP_EXT; + + $cwd = getcwd(); + chdir(dirname(__FILE__) . '/templates'); + + $this->run_template('includephp.html', array(), array(), array(), 'testing included php', $cache_file); + + $this->template->set_filenames(array('test' => 'includephp.html')); + $this->assertEquals('testing included php', $this->display('test'), "Testing $file"); + + chdir($cwd); + + phpbb::$config['tpl_allow_php'] = false; + } +*/ + public static function alter_block_array_data() + { + return array( + array( + 'outer', + array('VARIABLE' => 'before'), + false, + 'insert', + <<<EOT +outer - 0/4 - before +outer - 1/4 +middle - 0/2 +middle - 1/2 +outer - 2/4 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 3/4 +middle - 0/2 +middle - 1/2 +EOT +, + 'Test inserting before on top level block', + ), + array( + 'outer', + array('VARIABLE' => 'after'), + true, + 'insert', + <<<EOT +outer - 0/4 +middle - 0/2 +middle - 1/2 +outer - 1/4 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/4 +middle - 0/2 +middle - 1/2 +outer - 3/4 - after +EOT +, + 'Test inserting after on top level block', + ), + array( + 'outer', + array('VARIABLE' => 'pos #1'), + 1, + 'insert', + <<<EOT +outer - 0/4 +middle - 0/2 +middle - 1/2 +outer - 1/4 - pos #1 +outer - 2/4 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 3/4 +middle - 0/2 +middle - 1/2 +EOT +, + 'Test inserting at 1 on top level block', + ), + array( + 'outer', + array('VARIABLE' => 'pos #1'), + 0, + 'change', + <<<EOT +outer - 0/3 - pos #1 +middle - 0/2 +middle - 1/2 +outer - 1/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/3 +middle - 0/2 +middle - 1/2 +EOT +, + 'Test inserting at 1 on top level block', + ), + array( + 'outer[0].middle', + array('VARIABLE' => 'before'), + false, + 'insert', + <<<EOT +outer - 0/3 +middle - 0/3 - before +middle - 1/3 +middle - 2/3 +outer - 1/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/3 +middle - 0/2 +middle - 1/2 +EOT +, + 'Test inserting before on nested block', + ), + array( + 'outer[0].middle', + array('VARIABLE' => 'after'), + true, + 'insert', + <<<EOT +outer - 0/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 - after +outer - 1/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/3 +middle - 0/2 +middle - 1/2 +EOT +, + 'Test inserting after on nested block', + ), + array( + 'outer[0].middle', + array('VARIABLE' => 'pos #1'), + 1, + 'insert', + <<<EOT +outer - 0/3 +middle - 0/3 +middle - 1/3 - pos #1 +middle - 2/3 +outer - 1/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/3 +middle - 0/2 +middle - 1/2 +EOT +, + 'Test inserting at pos 1 on nested block', + ), + array( + 'outer[1].middle', + array('VARIABLE' => 'before'), + false, + 'insert', + <<<EOT +outer - 0/3 +middle - 0/2 +middle - 1/2 +outer - 1/3 +middle - 0/4 - before +middle - 1/4 +middle - 2/4 +middle - 3/4 +outer - 2/3 +middle - 0/2 +middle - 1/2 +EOT +, + 'Test inserting before on nested block (pos 1)', + ), + array( + 'outer[].middle', + array('VARIABLE' => 'before'), + false, + 'insert', + <<<EOT +outer - 0/3 +middle - 0/2 +middle - 1/2 +outer - 1/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/3 +middle - 0/3 - before +middle - 1/3 +middle - 2/3 +EOT +, + 'Test inserting before on nested block (end)', + ), + array( + 'outer.middle', + array('VARIABLE' => 'before'), + false, + 'insert', + <<<EOT +outer - 0/3 +middle - 0/2 +middle - 1/2 +outer - 1/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/3 +middle - 0/3 - before +middle - 1/3 +middle - 2/3 +EOT +, + 'Test inserting before on nested block (end)', + ), + ); + } + +/* + <<<EOT +outer - 0/3 +middle - 0/2 +middle - 1/2 +outer - 1/3 +middle - 0/3 +middle - 1/3 +middle - 2/3 +outer - 2/3 +middle - 0/2 +middle - 1/2 +EOT +, +*/ + + /** + * @dataProvider alter_block_array_data + public function test_alter_block_array($alter_block, array $vararray, $key, $mode, $expect, $description) + { + $this->template->set_filenames(array('test' => 'loop_nested.html')); + + // @todo Change this + $this->template->assign_block_vars('outer', array()); + $this->template->assign_block_vars('outer.middle', array()); + $this->template->assign_block_vars('outer.middle', array()); + $this->template->assign_block_vars('outer', array()); + $this->template->assign_block_vars('outer.middle', array()); + $this->template->assign_block_vars('outer.middle', array()); + $this->template->assign_block_vars('outer.middle', array()); + $this->template->assign_block_vars('outer', array()); + $this->template->assign_block_vars('outer.middle', array()); + $this->template->assign_block_vars('outer.middle', array()); + + $this->assertEquals("outer - 0/3\nmiddle - 0/2\nmiddle - 1/2\nouter - 1/3\nmiddle - 0/3\nmiddle - 1/3\nmiddle - 2/3\nouter - 2/3\nmiddle - 0/2\nmiddle - 1/2", $this->display('test'), 'Ensuring template is built correctly before modification'); + + $this->template->alter_block_array($alter_block, $vararray, $key, $mode); + $this->assertEquals($expect, $this->display('test'), $description); + } + */ +} diff --git a/tests/template/templates/_dummy_include.php b/tests/template/templates/_dummy_include.php new file mode 100644 index 0000000000..1de5dddf59 --- /dev/null +++ b/tests/template/templates/_dummy_include.php @@ -0,0 +1,3 @@ +<?php + +echo "testing included php"; diff --git a/tests/template/templates/basic.html b/tests/template/templates/basic.html new file mode 100644 index 0000000000..c1dd690260 --- /dev/null +++ b/tests/template/templates/basic.html @@ -0,0 +1,20 @@ +<!-- IF S_FALSE --> +fail +<!-- ENDIF --> +<!-- IF S_TRUE --> +pass +<!-- ENDIF --> +<!-- IF S_FALSE --> +fail +<!-- ELSEIF S_FALSE and not S_TRUE --> +fail +<!-- ELSE --> +pass +<!-- ENDIF --> +<!-- BEGIN empty --> +fail +<!-- BEGINELSE --> +pass +<!-- END empty --> + +<!-- DUMMY var --> diff --git a/tests/template/templates/define.html b/tests/template/templates/define.html new file mode 100644 index 0000000000..aec5c010fd --- /dev/null +++ b/tests/template/templates/define.html @@ -0,0 +1,41 @@ +<!-- DEFINE $VALUE = 'xyz' --> + +{$VALUE} + +<!-- DEFINE $VALUE = 'abc' --> + +{$VALUE} + +<!-- UNDEFINE $VALUE --> + +{$VALUE} + +<!-- DEFINE $VALUE --> + +<!-- BEGIN loop --> +<!-- DEFINE loop.$VALUE = loop.S_ROW_NUM --> +{loop.$VALUE} +<!-- UNDEFINE $VALUE --> +{loop.$VALUE} +<!-- UNDEFINE loop.$VALUE --> +{loop.$VALUE} + +<!-- END loop --> + +<!-- BEGIN test --> + <!-- BEGIN deep --> + <!-- BEGIN defines --> +<!-- DEFINE test.deep.defines.$VALUE = 12 * 12 --> + +{test.deep.defines.$VALUE} + +<!-- UNDEFINE $VALUE --> + +{test.deep.defines.$VALUE} + +<!-- UNDEFINE test.deep.defines.$VALUE --> + +{test.deep.defines.$VALUE} + <!-- END defines --> + <!-- END deep --> +<!-- END test --> diff --git a/tests/template/templates/expressions.html b/tests/template/templates/expressions.html new file mode 100644 index 0000000000..47a164e481 --- /dev/null +++ b/tests/template/templates/expressions.html @@ -0,0 +1,88 @@ +<!-- IF 10 is even -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 9 is even -->fail<!-- ELSE -->pass<!-- ENDIF --> + +<!-- IF not 390 is even -->fail<!-- ELSE -->pass<!-- ENDIF --> + +<!-- IF 9 is odd -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 32 is odd -->fail<!-- ELSE -->pass<!-- ENDIF --> + +<!-- IF 32 is div by 16 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 10 is not even -->fail<!-- ELSE -->pass<!-- ENDIF --> + +<!-- IF 24 == 24 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 24 eq 24 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF ((((((24 == 24)))))) -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF 24 != 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 24 <> 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 24 ne 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 24 neq 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF 10 lt 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 10 < 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF 10 le 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 10 lte 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 10 <= 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 20 le 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 20 lte 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 20 <= 20 -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF 9 gt 1 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 9 > 1 -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF 9 >= 1 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 9 gte 1 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 9 ge 1 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 9 >= 9 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 9 gte 9 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 9 ge 9 -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF true && (10 > 4) -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF true and (10 > 4) -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF false || true -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF false or true -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF !false -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF !! true -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF not false -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF not not not false -->pass<!-- ELSE -->fail<!-- ENDIF --> + + +<!-- IF 6 % 4 == 2 -->pass<!-- ELSE -->fail<!-- ENDIF --> + +<!-- IF 24 mod 12 == 0 -->pass<!-- ELSE -->fail<!-- ENDIF --> diff --git a/tests/template/templates/if.html b/tests/template/templates/if.html new file mode 100644 index 0000000000..8ec3e66449 --- /dev/null +++ b/tests/template/templates/if.html @@ -0,0 +1,11 @@ +<!-- IF S_VALUE --> +1 +<!-- ELSEIF S_OTHER_VALUE --> +2 +<!-- ELSE --> +0 +<!-- ENDIF --> + +<!-- IF !!(S_VALUE > S_OTHER_VALUE) --> +0 +<!-- ENDIF --> diff --git a/tests/template/templates/include.html b/tests/template/templates/include.html new file mode 100644 index 0000000000..730d713d65 --- /dev/null +++ b/tests/template/templates/include.html @@ -0,0 +1 @@ +<!-- INCLUDE variable.html --> diff --git a/tests/template/templates/includephp.html b/tests/template/templates/includephp.html new file mode 100644 index 0000000000..42c78b9377 --- /dev/null +++ b/tests/template/templates/includephp.html @@ -0,0 +1 @@ +<!-- INCLUDEPHP _dummy_include.php --> diff --git a/tests/template/templates/lang.html b/tests/template/templates/lang.html new file mode 100644 index 0000000000..2b5ea1cafe --- /dev/null +++ b/tests/template/templates/lang.html @@ -0,0 +1,3 @@ +{L_VARIABLE} + +{LA_VARIABLE} diff --git a/tests/template/templates/loop.html b/tests/template/templates/loop.html new file mode 100644 index 0000000000..f1e1bf7e53 --- /dev/null +++ b/tests/template/templates/loop.html @@ -0,0 +1,23 @@ +<!-- BEGIN loop --> +loop +<!-- BEGINELSE --> +noloop +<!-- END loop --> + +<!-- IF .loop --> +loop +<!-- ELSE --> +noloop +<!-- ENDIF --> + +<!-- IF .loop == 2 --> +loop +<!-- ENDIF --> + +<!-- BEGIN loop --> +<!-- BEGIN !block --> + +loop#{loop.S_ROW_NUM}-block#{block.S_ROW_NUM} + +<!-- END !block --> +<!-- END loop --> diff --git a/tests/template/templates/loop_advanced.html b/tests/template/templates/loop_advanced.html new file mode 100644 index 0000000000..1ed70f28c5 --- /dev/null +++ b/tests/template/templates/loop_advanced.html @@ -0,0 +1,59 @@ +<!-- BEGIN loop --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(0) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(0,-1) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(1) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(1,1) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(0,1) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(2,4) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(0,-7) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(-2,6) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> + +<!-- BEGIN loop(-2,-1) --> +{loop.S_FIRST_ROW} +{loop.S_ROW_NUM} +{loop.S_LAST_ROW} +<!-- END loop --> diff --git a/tests/template/templates/loop_expressions.html b/tests/template/templates/loop_expressions.html new file mode 100644 index 0000000000..6bff53f388 --- /dev/null +++ b/tests/template/templates/loop_expressions.html @@ -0,0 +1,11 @@ +<!-- BEGIN loop --> + +<!-- IF loop.S_ROW_NUM is even by 4 -->on<!-- ELSE -->off<!-- ENDIF --> + +<!-- END loop --> + +<!-- BEGIN loop --> + +<!-- IF loop.S_ROW_NUM is odd by 3 -->on<!-- ELSE -->off<!-- ENDIF --> + +<!-- END loop --> diff --git a/tests/template/templates/loop_nested.html b/tests/template/templates/loop_nested.html new file mode 100644 index 0000000000..571df97b4c --- /dev/null +++ b/tests/template/templates/loop_nested.html @@ -0,0 +1,8 @@ +<!-- BEGIN outer --> + {outer.S_BLOCK_NAME} - {outer.S_ROW_NUM}/{outer.S_NUM_ROWS}<!-- IF outer.VARIABLE --> - {outer.VARIABLE}<!-- ENDIF --> + + <!-- BEGIN middle --> + {middle.S_BLOCK_NAME} - {middle.S_ROW_NUM}/{middle.S_NUM_ROWS}<!-- IF middle.VARIABLE --> - {middle.VARIABLE}<!-- ENDIF --> + + <!-- END middle --> +<!-- END outer --> diff --git a/tests/template/templates/loop_vars.html b/tests/template/templates/loop_vars.html new file mode 100644 index 0000000000..1ecf49bdf2 --- /dev/null +++ b/tests/template/templates/loop_vars.html @@ -0,0 +1,23 @@ +<!-- BEGIN loop --> +<!-- IF loop.S_FIRST_ROW -->first<!-- ENDIF --> + +{loop.S_ROW_COUNT} + +{loop.S_ROW_NUM} + +{loop.S_NUM_ROWS} + +{loop.VARIABLE} + +<!-- IF loop.VARIABLE -->set<!-- ENDIF --> + +<!-- IF loop.S_LAST_ROW -->last<!-- ENDIF --> +<!-- BEGIN inner --> + +{inner.S_ROW_NUM} + +<!-- IF inner.S_LAST_ROW and inner.S_ROW_NUM and inner.S_NUM_ROWS -->last inner<!-- ENDIF --> + +<!-- END inner --> +<!-- END loop --> +<!-- IF .loop.inner -->inner loop<!-- ENDIF --> diff --git a/tests/template/templates/php.html b/tests/template/templates/php.html new file mode 100644 index 0000000000..07a260cdb3 --- /dev/null +++ b/tests/template/templates/php.html @@ -0,0 +1 @@ +<!-- PHP -->echo "test";<!-- ENDPHP --> diff --git a/tests/template/templates/variable.html b/tests/template/templates/variable.html new file mode 100644 index 0000000000..f68f91597c --- /dev/null +++ b/tests/template/templates/variable.html @@ -0,0 +1 @@ +{VARIABLE} diff --git a/tests/test_framework/framework.php b/tests/test_framework/framework.php new file mode 100644 index 0000000000..01afd4e37e --- /dev/null +++ b/tests/test_framework/framework.php @@ -0,0 +1,29 @@ +<?php + +define('IN_PHPBB', true); +$phpbb_root_path = '../phpBB/'; +$phpEx = 'php'; +$table_prefix = ''; + +// If we are on PHP >= 6.0.0 we do not need some code +if (version_compare(PHP_VERSION, '6.0.0-dev', '>=')) +{ + define('STRIP', false); +} +else +{ + @set_magic_quotes_runtime(0); + define('STRIP', (get_magic_quotes_gpc()) ? true : false); +} + +require_once $phpbb_root_path . 'includes/constants.php'; + +// require at least PHPUnit 3.3.0 +require_once 'PHPUnit/Runner/Version.php'; +if (version_compare(PHPUnit_Runner_Version::id(), '3.3.0', '<')) +{ + trigger_error('PHPUnit >= 3.3.0 required'); +} + +require_once 'PHPUnit/Framework.php'; +require_once 'test_framework/phpbb_test_case.php';
\ No newline at end of file diff --git a/tests/test_framework/phpbb_test_case.php b/tests/test_framework/phpbb_test_case.php new file mode 100644 index 0000000000..d5fdcf9889 --- /dev/null +++ b/tests/test_framework/phpbb_test_case.php @@ -0,0 +1,30 @@ +<?php + +class phpbb_test_case extends PHPUnit_Framework_TestCase +{ + protected $expectedTriggerError = false; + + public function setExpectedTriggerError($errno, $message = '') + { + $exceptionName = ''; + switch ($errno) + { + case E_NOTICE: + case E_STRICT: + PHPUnit_Framework_Error_Notice::$enabled = true; + $exceptionName = 'PHPUnit_Framework_Error_Notice'; + break; + + case E_WARNING: + PHPUnit_Framework_Error_Warning::$enabled = true; + $exceptionName = 'PHPUnit_Framework_Error_Warning'; + break; + + default: + $exceptionName = 'PHPUnit_Framework_Error'; + break; + } + $this->expectedTriggerError = true; + $this->setExpectedException($exceptionName, (string) $message, $errno); + } +}
\ No newline at end of file diff --git a/tests/text_processing/all_tests.php b/tests/text_processing/all_tests.php new file mode 100644 index 0000000000..d53dd1127e --- /dev/null +++ b/tests/text_processing/all_tests.php @@ -0,0 +1,41 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +if (!defined('PHPUnit_MAIN_METHOD')) +{ + define('PHPUnit_MAIN_METHOD', 'phpbb_text_processing_all_tests::main'); +} + +require_once 'test_framework/framework.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +require_once 'text_processing/make_clickable.php'; + +class phpbb_text_processing_all_tests +{ + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + $suite = new PHPUnit_Framework_TestSuite('phpBB Text Processing Tools'); + + $suite->addTestSuite('phpbb_text_processing_make_clickable_test'); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'phpbb_text_processing_all_tests::main') +{ + phpbb_text_processing_all_tests::main(); +} diff --git a/tests/text_processing/make_clickable.php b/tests/text_processing/make_clickable.php new file mode 100644 index 0000000000..25199c428a --- /dev/null +++ b/tests/text_processing/make_clickable.php @@ -0,0 +1,106 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once 'test_framework/framework.php'; + +require_once '../phpBB/includes/functions.php'; +require_once '../phpBB/includes/functions_content.php'; + +class phpbb_text_processing_make_clickable_test extends phpbb_test_case +{ + public static function make_clickable_data() + { + // value => whether it should work + $prefix_texts = array( + '' => true, + "np \n" => true, + 'bp text ' => true, + 'cp text>' => true, + 'ep text.' => array('w' => false), // doesn't work for www. type urls, but for everything else + ); + $suffix_texts = array( + '' => true, + "\n ns" => true, + ' bs text.' => true, + '>cs text' => true, + '"ds text' => true, + '. es text.' => true, + ', fs text.' => true, + ); + + $urls = array( + 'http://example.com' => array('tag' => 'm', 'url' => false, 'text' => false), // false means same as key + 'http://example.com/' => array('tag' => 'm', 'url' => false, 'text' => false), + 'http://example.com/path?query=abc' => array('tag' => 'm', 'url' => false, 'text' => false), + 'http://example.com/1' => array('tag' => 'm', 'url' => false, 'text' => false), + 'http://example.com/some/very/long/path/with/over/55/characters?and=a&long=query&too=1' => array('tag' => 'm', 'url' => false, 'text' => 'http://example.com/some/very/long/path/ ... uery&too=1'), + 'http://localhost' => array('tag' => 'm', 'url' => false, 'text' => false), + 'http://localhost/#abc' => array('tag' => 'm', 'url' => false, 'text' => false), + + 'www.example.com/path/' => array('tag' => 'w', 'url' => 'http://www.example.com/path/', 'text' => false), + 'randomwww.example.com/path/' => false, + + 'http://thisdomain.org' => array('tag' => 'm', 'url' => false, 'text' => false), + 'http://thisdomain.org/' => array('tag' => 'm', 'url' => false, 'text' => false), + 'http://thisdomain.org/1' => array('tag' => 'l', 'url' => false, 'text' => '1'), + 'http://thisdomain.org/path/some?query=abc#test' => array('tag' => 'l', 'url' => false, 'text' => 'path/some?query=abc#test'), + + 'javascript:www.example.com/' => false, + ); + + $test_data = array(); + + // run the test for each combination + foreach ($prefix_texts as $prefix => $prefix_success) + { + foreach ($suffix_texts as $suffix => $suffix_success) + { + foreach ($urls as $url => $url_type) + { + $input = $prefix . $url . $suffix; + // no valid url => no change + $output = $input; + + if ( + ($prefix_success && $suffix_success && is_array($url_type)) && + // handle except syntax for prefix/suffix + (!is_array($prefix_success) || !isset($prefix_success[$url_type['tag']]) || $prefix_success[$url_type['tag']] == true) && + (!is_array($suffix_success) || !isset($suffix_success[$url_type['tag']]) || $suffix_success[$url_type['tag']] == true) + ) + { + // false means it's the same as the url, less typing + $url_type['url'] = ($url_type['url']) ? $url_type['url'] : $url; + $url_type['text'] = ($url_type['text']) ? $url_type['text'] : $url; + + $class = ($url_type['tag'] === 'l') ? 'postlink-local' : 'postlink'; + + // replace the url with the desired output format + $output = $prefix . '<!-- ' . $url_type['tag'] . ' --><a class="' . $class . '" href="' . $url_type['url'] . '">' . $url_type['text'] . '</a><!-- ' . $url_type['tag'] . ' -->' . $suffix; + } + $test_data[] = array($input, $output); + } + } + } + + return $test_data; + } + + /** + * @dataProvider make_clickable_data + */ + public function test_make_clickable($input, $expected) + { + $result = make_clickable($input, 'http://thisdomain.org'); + + $label = 'Making text clickable: ' . $input; + $this->assertEquals($expected, $result, $label); + } + +} diff --git a/tests/utf/all_tests.php b/tests/utf/all_tests.php new file mode 100644 index 0000000000..bccabf6529 --- /dev/null +++ b/tests/utf/all_tests.php @@ -0,0 +1,43 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +if (!defined('PHPUnit_MAIN_METHOD')) +{ + define('PHPUnit_MAIN_METHOD', 'phpbb_utf_all_tests::main'); +} + +require_once 'test_framework/framework.php'; +require_once 'PHPUnit/TextUI/TestRunner.php'; + +require_once 'utf/utf8_wordwrap_test.php'; +require_once 'utf/utf8_clean_string_test.php'; + +class phpbb_utf_all_tests +{ + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + public static function suite() + { + $suite = new PHPUnit_Framework_TestSuite('phpBB Unicode Transformation Format'); + + $suite->addTestSuite('phpbb_utf_utf8_wordwrap_test'); + $suite->addTestSuite('phpbb_utf_utf8_clean_string_test'); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'phpbb_utf_all_tests::main') +{ + phpbb_utf_all_tests::main(); +} diff --git a/tests/utf/utf8_clean_string_test.php b/tests/utf/utf8_clean_string_test.php new file mode 100644 index 0000000000..bd9e3f5f26 --- /dev/null +++ b/tests/utf/utf8_clean_string_test.php @@ -0,0 +1,32 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once 'test_framework/framework.php'; +require_once '../phpBB/includes/utf/utf_tools.php'; + +class phpbb_utf_utf8_clean_string_test extends phpbb_test_case +{ + public static function cleanable_strings() + { + return array( + array('MiXed CaSe', 'mixed case', 'Checking case folding'), + array(' many spaces ', 'many spaces', 'Checking whitespace reduction'), + array("we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters", 'weird characters', 'Checking confusables replacement'), + ); + } + + /** + * @dataProvider cleanable_strings + */ + public function test_utf8_clean_string($input, $output, $label) + { + $this->assertEquals($output, utf8_clean_string($input), $label); + } +} diff --git a/tests/utf/utf8_wordwrap_test.php b/tests/utf/utf8_wordwrap_test.php new file mode 100644 index 0000000000..51245ec418 --- /dev/null +++ b/tests/utf/utf8_wordwrap_test.php @@ -0,0 +1,84 @@ +<?php +/** +* +* @package testing +* @version $Id$ +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once 'test_framework/framework.php'; +require_once '../phpBB/includes/utf/utf_tools.php'; + +class phpbb_utf_utf8_wordwrap_test extends phpbb_test_case +{ + public function test_utf8_wordwrap_ascii() + { + // if the input is all ascii it should work exactly like php's wordwrap + + $text = 'The quick brown fox jumped over the lazy dog.'; + + $php_wordwrap = wordwrap($text, 20); + $phpbb_utf8_wordwrap = utf8_wordwrap($text, 20); + $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, "Checking ASCII standard behaviour with length 20"); + + $php_wordwrap = wordwrap($text, 30, "<br />\n"); + $phpbb_utf8_wordwrap = utf8_wordwrap($text, 30, "<br />\n"); + $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, "Checking ASCII special break string with length 30"); + + $text = 'A very long woooooooooooord.'; + + $php_wordwrap = wordwrap($text, 8, "\n"); + $phpbb_utf8_wordwrap = utf8_wordwrap($text, 8, "\n"); + $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, 'Checking ASCII not cutting long words'); + + $php_wordwrap = wordwrap($text, 8, "\n", true); + $phpbb_utf8_wordwrap = utf8_wordwrap($text, 8, "\n", true); + $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, 'Checking ASCII cutting long words'); + } + + /** + * Helper function that generates meaningless greek text + */ + private function turn_into_greek($string) + { + $greek_chars = array("\xCE\x90", "\xCE\x91", "\xCE\x92", "\xCE\x93", "\xCE\x94", "\xCE\x95", "\xCE\x96", "\xCE\x97", "\xCE\x98", "\xCE\x99"); + + $greek = ''; + for ($i = 0, $n = strlen($string); $i < $n; $i++) + { + // replace each number with the character from the array + if (ctype_digit($string[$i])) + { + $greek .= $greek_chars[(int) $string[$i]]; + } + else + { + $greek .= $string[$i]; + } + } + + return $greek; + } + + public function test_utf8_wordwrap_utf8() + { + $text = "0123456 0123 012345 01234"; + $greek = $this->turn_into_greek($text); + + $expected = $this->turn_into_greek(wordwrap($text, 10)); + $phpbb_utf8_wordwrap = utf8_wordwrap($greek, 10); + $this->assertEquals($expected, $phpbb_utf8_wordwrap, 'Checking UTF-8 standard behaviour with length 10'); + } + + public function test_utf8_wordwrap_utf8_cut() + { + $text = "0123456 0123 012345 01234"; + $greek = $this->turn_into_greek($text); + + $expected = $this->turn_into_greek(wordwrap($text, 5, "\n", true)); + $phpbb_utf8_wordwrap = utf8_wordwrap($greek, 5, "\n", true); + $this->assertEquals($expected, $phpbb_utf8_wordwrap, 'Checking UTF-8 cutting long words'); + } +} |