diff --git a/.editorconfig b/.editorconfig index 9088a1657..d88e75a28 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,15 +1,19 @@ ; http://editorconfig.org/ +root = true + [*] indent_style = space indent_size = 4 +end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[inc/{geshi,phpseclib}/**] +[{vendor,inc/phpseclib}/**] ; Use editor default (possible autodetection). indent_style = indent_size = -trim_trailing_whitespace = false -insert_final_newline = false +end_of_line = +trim_trailing_whitespace = +insert_final_newline = diff --git a/.gitattributes b/.gitattributes index 1012087d4..6beb1fb7a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,8 @@ .gitignore export-ignore .editorconfig export-ignore .travis.yml export-ignore +composer.json export-ignore +composer.lock export-ignore _test export-ignore _cs export-ignore lib/plugins/testing export-ignore diff --git a/.gitignore b/.gitignore index bb39ba7cf..7410ee1c3 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ !/lib/plugins/popularity !/lib/plugins/revert !/lib/plugins/safefnrecode +!/lib/plugins/styling !/lib/plugins/testing !/lib/plugins/usermanager !/lib/plugins/action.php @@ -56,3 +57,17 @@ !/lib/plugins/remote.php !/lib/plugins/syntax.php lib/images/*/local/* + +# composer default ignores +composer.phar +vendor/bin/* +vendor/*/*/phpunit.xml +vendor/*/*/.travis.yml +vendor/*/*/bin/* +vendor/*/*/tests/* +vendor/*/*/test/* +vendor/*/*/doc/* +vendor/*/*/docs/* +vendor/*/*/contrib/* +vendor/splitbrain/php-archive/apigen.neon +vendor/splitbrain/php-archive/generate-api.sh diff --git a/.htaccess.dist b/.htaccess.dist index 5724a6e04..1d2bd418e 100644 --- a/.htaccess.dist +++ b/.htaccess.dist @@ -6,10 +6,20 @@ ## make sure nobody gets the htaccess, README, COPYING or VERSION files - Order allow,deny - Deny from all + + Require all denied + + + Order allow,deny + Deny from all + +## Don't allow access to git directories + + RedirectMatch 404 /\.git + + ## Uncomment these rules if you want to have nice URLs using ## $conf['userewrite'] = 1 - not needed for rewrite mode 2 #RewriteEngine on diff --git a/.travis.yml b/.travis.yml index 0bef94048..a0aa15296 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,23 @@ language: php +sudo: false php: + - "7.0" - "5.6" - "5.5" - "5.4" - "5.3" + - "hhvm" +env: + - DISABLE_FUNCTIONS= + - DISABLE_FUNCTIONS="gzopen" +matrix: + allow_failures: + - php: "hhvm" notifications: irc: channels: - "chat.freenode.net#dokuwiki" on_success: change on_failure: change -install: - - wget https://phar.phpunit.de/phpunit-4.3.5.phar -O _test/phpunit - - chmod 755 _test/phpunit -script: cd _test && ./phpunit --verbose --stderr +before_script: echo "disable_functions=$DISABLE_FUNCTIONS" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini +script: cd _test && phpunit --verbose --stderr diff --git a/README b/README index 35de49ab1..1611a6df1 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ at http://www.dokuwiki.org/ For Installation Instructions see http://www.dokuwiki.org/install -DokuWiki - 2004-2014 (c) Andreas Gohr +DokuWiki - 2004-2015 (c) Andreas Gohr and the DokuWiki Community See COPYING and file headers for license info diff --git a/_cs/DokuWiki/Sniffs/PHP/DeprecatedFunctionsSniff.php b/_cs/DokuWiki/Sniffs/PHP/DeprecatedFunctionsSniff.php index c5d14377b..c15a5be02 100644 --- a/_cs/DokuWiki/Sniffs/PHP/DeprecatedFunctionsSniff.php +++ b/_cs/DokuWiki/Sniffs/PHP/DeprecatedFunctionsSniff.php @@ -39,7 +39,7 @@ class DokuWiki_Sniffs_PHP_DeprecatedFunctionsSniff extends Generic_Sniffs_PHP_Fo * * @var array(string => string|null) */ - protected $forbiddenFunctions = array( + public $forbiddenFunctions = array( 'setCorrectLocale' => null, 'html_attbuild' => 'buildAttributes', 'io_runcmd' => null, diff --git a/_cs/DokuWiki/Sniffs/PHP/DiscouragedFunctionsSniff.php b/_cs/DokuWiki/Sniffs/PHP/DiscouragedFunctionsSniff.php index 9cd9a7d36..bd51b1166 100644 --- a/_cs/DokuWiki/Sniffs/PHP/DiscouragedFunctionsSniff.php +++ b/_cs/DokuWiki/Sniffs/PHP/DiscouragedFunctionsSniff.php @@ -39,7 +39,7 @@ class DokuWiki_Sniffs_PHP_DiscouragedFunctionsSniff extends Generic_Sniffs_PHP_F * * @var array(string => string|null) */ - protected $forbiddenFunctions = array( + public $forbiddenFunctions = array( 'date' => 'dformat', 'strftime' => 'dformat', ); diff --git a/_test/phpunit.xml b/_test/phpunit.xml index 25506b1ae..6e2509749 100644 --- a/_test/phpunit.xml +++ b/_test/phpunit.xml @@ -18,6 +18,12 @@ + + + flaky + + + ../ diff --git a/_test/tests/general/general_languagelint.php b/_test/tests/general/general_languagelint.test.php similarity index 100% rename from _test/tests/general/general_languagelint.php rename to _test/tests/general/general_languagelint.test.php diff --git a/_test/tests/inc/PassHash.test.php b/_test/tests/inc/PassHash.test.php index 1d34aa696..1bc4b95bc 100644 --- a/_test/tests/inc/PassHash.test.php +++ b/_test/tests/inc/PassHash.test.php @@ -17,6 +17,24 @@ class PassHash_test extends DokuWikiTest { $this->assertEquals('fbdb1d1b18aa6c08324b7d64b71fb76370690e1d', PassHash::hmac('sha1','','')); $this->assertEquals('80070713463e7749b90c2dc24911e275', PassHash::hmac('md5','The quick brown fox jumps over the lazy dog','key')); $this->assertEquals('de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9', PassHash::hmac('sha1','The quick brown fox jumps over the lazy dog','key')); - } -} \ No newline at end of file + + function test_djangopbkdf2() { + if(!function_exists('hash_pbkdf2') || !in_array('sha256', hash_algos())){ + $this->markTestSkipped('missing hash functions for djangopbkdf2 password tests'); + return; + } + + $ph = new PassHash(); + $knownpasses = array ( + 'pbkdf2_sha256$24000$LakQQ2OOTO1v$dmUgz8V7zcpaoBSA3MV76J5a4rzrszF0NpxGx6HRBbE=', + 'pbkdf2_sha256$24000$PXogIZpE4gaK$F/P/L5SRrbb6taOGEr4w6DhxjMzNAj1jEWTPyAUn8WU=', + 'pbkdf2_sha256$24000$vtn5APnhirmB$/jzJXYvm78X8/FCOMhGUmcCy0iWhtk0L1hcBWN1AYZc=', + 'pbkdf2_sha256$24000$meyCtGKrS5Ai$vkMfMzB/yGFKplmXujgtfl3OGR27AwOQmP+YeRP6lbw=', + 'pbkdf2_sha256$24000$M8ecC8zfqLmJ$l6cIa/Od+m56VMm9hJbdPNhTXZykPVbUGGTPx7/VRE4=', + ); + foreach($knownpasses as $known) { + $this->assertTrue($ph->verify_hash('P4zzW0rd!', $known)); + } + } +} diff --git a/_test/tests/inc/auth_password.test.php b/_test/tests/inc/auth_password.test.php index 07b9f5bb2..71b0dfb4c 100644 --- a/_test/tests/inc/auth_password.test.php +++ b/_test/tests/inc/auth_password.test.php @@ -2,7 +2,7 @@ class auth_password_test extends DokuWikiTest { - // hashes for the password foo$method, using abcdefgh as salt + // hashes for the password foo$method, using abcdefgh12345678912345678912345678 as salt var $passes = array( 'smd5' => '$1$abcdefgh$SYbjm2AEvSoHG7Xapi8so.', 'apr1' => '$apr1$abcdefgh$C/GzYTF4kOVByYLEoD5X4.', @@ -16,15 +16,32 @@ class auth_password_test extends DokuWikiTest { 'kmd5' => 'a579299436d7969791189acadd86fcb716', 'djangomd5' => 'md5$abcde$d0fdddeda8cd92725d2b54148ac09158', 'djangosha1' => 'sha1$abcde$c8e65a7f0acc9158843048a53dcc5a6bc4d17678', - 'sha512' => '$6$abcdefgh12345678$J9.zOcgx0lotwZdcz0uulA3IVQMinZvFZVjA5vapRLVAAqtay23XD4xeeUxQ3B4JvDWYFBIxVWW1tOYlHX13k1' + ); + function __construct() { + if(defined('CRYPT_SHA512') && CRYPT_SHA512 == 1) { + // Check SHA512 only if available in this PHP + $this->passes['sha512'] = '$6$abcdefgh12345678$J9.zOcgx0lotwZdcz0uulA3IVQMinZvFZVjA5vapRLVAAqtay23XD4xeeUxQ3B4JvDWYFBIxVWW1tOYlHX13k1'; + } + if(function_exists('hash_pbkdf2')) { + if(in_array('sha256', hash_algos())) { + $this->passes['djangopbkdf2_sha256'] = 'pbkdf2_sha256$24000$abcdefgh1234$R23OyZJ0nGHLG6MvPNfEkV5AOz3jUY5zthByPXs2gn0='; + } + if(in_array('sha1', hash_algos())) { + $this->passes['djangopbkdf2_sha1'] = 'pbkdf2_sha1$24000$abcdefgh1234$pOliX4vV1hgOv7lFNURIHHx41HI='; + } + } + } + function test_cryptPassword(){ foreach($this->passes as $method => $hash){ $info = "testing method $method"; - $this->assertEquals(auth_cryptPassword('foo'.$method, $method,'abcdefgh12345678912345678912345678'), - $hash, $info); + $this->assertEquals( + $hash, + auth_cryptPassword('foo'.$method, $method,'abcdefgh12345678912345678912345678'), + $info); } } diff --git a/_test/tests/inc/cache_use.test.php b/_test/tests/inc/cache_use.test.php index 3ea212d50..c0c12580a 100644 --- a/_test/tests/inc/cache_use.test.php +++ b/_test/tests/inc/cache_use.test.php @@ -4,6 +4,8 @@ * Class cache_use_test * * Tests if caching can actually be used + * + * @todo tests marked as flaky until Ticket #694 has been fixed */ class cache_use_test extends DokuWikiTest { /** @var cache_renderer $cache */ @@ -28,18 +30,11 @@ class cache_use_test extends DokuWikiTest { touch($this->cache->cache, $time); } - function test_use() { - $this->markTestSkipped('Disabled until Ticket #694 has been fixed'); - return; - - $this->assertTrue($this->cache->useCache()); - } - /** * In all the following tests the cache should not be usable * as such, they are meaningless if test_use didn't pass. * - * @depends test_use + * @group flaky */ function test_purge() { /* @var Input $INPUT */ @@ -51,7 +46,7 @@ class cache_use_test extends DokuWikiTest { } /** - * @depends test_use + * @group flaky */ function test_filedependency() { // give the dependent src file the same mtime as the cache @@ -60,7 +55,7 @@ class cache_use_test extends DokuWikiTest { } /** - * @depends test_use + * @group flaky */ function test_age() { // need to age both our source file & the cache @@ -74,7 +69,7 @@ class cache_use_test extends DokuWikiTest { } /** - * @depends test_use + * @group flaky */ function test_confnocaching() { global $conf; @@ -83,4 +78,4 @@ class cache_use_test extends DokuWikiTest { $this->assertFalse($this->cache->useCache()); $this->assertNotEmpty($this->cache->_nocache); } -} \ No newline at end of file +} diff --git a/_test/tests/inc/common_blank.test.php b/_test/tests/inc/common_blank.test.php new file mode 100644 index 000000000..9df35936a --- /dev/null +++ b/_test/tests/inc/common_blank.test.php @@ -0,0 +1,52 @@ +assertEquals($test[1], blank($test[0]), "using " . var_export($test[0], true)); + } + } + + function test_trim() { + $whitespace = " \t\r\n"; + $this->assertFalse(blank($whitespace), "using default \$trim value"); + $this->assertFalse(blank($whitespace, false), "using \$trim = false"); + $this->assertTrue(blank($whitespace, true), "using \$trim = true"); + } + + function test_undefined() { + $undef = array(); + $this->assertTrue(blank($var), "using undefined/unitialised variable"); + $this->assertTrue(blank($undef['nope']), "using undefined array index"); + $this->assertTrue(blank($this->nope), "using unset object property"); + } + +} diff --git a/_test/tests/inc/common_saveWikiText.test.php b/_test/tests/inc/common_saveWikiText.test.php new file mode 100644 index 000000000..800e20952 --- /dev/null +++ b/_test/tests/inc/common_saveWikiText.test.php @@ -0,0 +1,145 @@ +assertFileNotExists($file); + saveWikiText($page, 'teststring', 'first save', false); + $this->assertFileExists($file); + $lastmod = filemtime($file); + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(1, count($revisions)); + $revinfo = $pagelog->getRevisionInfo($revisions[0]); + $this->assertEquals('first save', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_CREATE, $revinfo['type']); + + sleep(1); // wait for new revision ID + + // save with same content should be ignored + saveWikiText($page, 'teststring', 'second save', false); + clearstatcache(false, $file); + $this->assertEquals($lastmod, filemtime($file)); + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(1, count($revisions)); + + // update the page with new text + saveWikiText($page, 'teststring2', 'third save', false); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(2, count($revisions)); + $revinfo = $pagelog->getRevisionInfo($revisions[0]); + $this->assertEquals('third save', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); + + sleep(1); // wait for new revision ID + + // add a minor edit (unauthenticated) + saveWikiText($page, 'teststring3', 'fourth save', true); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(3, count($revisions)); + $revinfo = $pagelog->getRevisionInfo($revisions[0]); + $this->assertEquals('fourth save', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); + + sleep(1); // wait for new revision ID + + // add a minor edit (authenticated) + $_SERVER['REMOTE_USER'] = 'user'; + saveWikiText($page, 'teststring4', 'fifth save', true); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(4, count($revisions)); + $revinfo = $pagelog->getRevisionInfo($revisions[0]); + $this->assertEquals('fifth save', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_MINOR_EDIT, $revinfo['type']); + + sleep(1); // wait for new revision ID + + // delete + saveWikiText($page, '', 'sixth save', false); + clearstatcache(false, $file); + $this->assertFileNotExists($file); + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(5, count($revisions)); + $revinfo = $pagelog->getRevisionInfo($revisions[0]); + $this->assertEquals('sixth save', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_DELETE, $revinfo['type']); + + sleep(1); // wait for new revision ID + + // restore + $REV = $lastmod; + saveWikiText($page, 'teststring4', 'seventh save', true); + clearstatcache(false, $file); + $this->assertFileExists($file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(6, count($revisions)); + $revinfo = $pagelog->getRevisionInfo($revisions[0]); + $this->assertEquals('seventh save', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_REVERT, $revinfo['type']); + $this->assertEquals($REV, $revinfo['extra']); + $REV = ''; + + sleep(1); // wait for new revision ID + + // create external edit + file_put_contents($file, 'teststring5'); + + sleep(1); // wait for new revision ID + + // save on top of external edit + saveWikiText($page, 'teststring6', 'eigth save', false); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + + $pagelog = new PageChangeLog($page); + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertEquals(8, count($revisions)); // two more revisions now! + $revinfo = $pagelog->getRevisionInfo($revisions[0]); + $this->assertEquals('eigth save', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); + + $revinfo = $pagelog->getRevisionInfo($revisions[1]); + $this->assertEquals('external edit', $revinfo['sum']); + $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); + + } +} diff --git a/_test/tests/inc/form/buttonelement.test.php b/_test/tests/inc/form/buttonelement.test.php new file mode 100644 index 000000000..8e1a7e1e2 --- /dev/null +++ b/_test/tests/inc/form/buttonelement.test.php @@ -0,0 +1,40 @@ +addButton('foo', 'Hello World')->val('bam')->attr('type', 'submit'); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $input = $pq->find('button[name=foo]'); + $this->assertTrue($input->length == 1); + $this->assertEquals('bam', $input->val()); + $this->assertEquals('submit', $input->attr('type')); + $this->assertEquals('Hello World', $input->text()); // tags were escaped + + $b = $input->find('b'); // no tags found + $this->assertTrue($b->length == 0); + } + + function test_html() { + $form = new Form\Form(); + $form->addButtonHTML('foo', 'Hello World')->val('bam')->attr('type', 'submit'); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $input = $pq->find('button[name=foo]'); + $this->assertTrue($input->length == 1); + $this->assertEquals('bam', $input->val()); + $this->assertEquals('submit', $input->attr('type')); + $this->assertEquals('Hello World', $input->text()); // tags are stripped here + + $b = $input->find('b'); // tags found + $this->assertTrue($b->length == 1); + } +} diff --git a/_test/tests/inc/form/checkableelement.test.php b/_test/tests/inc/form/checkableelement.test.php new file mode 100644 index 000000000..e1491f6ec --- /dev/null +++ b/_test/tests/inc/form/checkableelement.test.php @@ -0,0 +1,51 @@ +addRadioButton('foo', 'label text first')->val('first')->attr('checked', 'checked'); + $form->addRadioButton('foo', 'label text second')->val('second'); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $input = $pq->find('input[name=foo]'); + $this->assertTrue($input->length == 2); + + $label = $pq->find('label'); + $this->assertTrue($label->length == 2); + + $inputs = $pq->find('input[name=foo]'); + $this->assertEquals('first', pq($inputs->elements[0])->val()); + $this->assertEquals('second', pq($inputs->elements[1])->val()); + $this->assertEquals('checked', pq($inputs->elements[0])->attr('checked')); + $this->assertEquals('', pq($inputs->elements[1])->attr('checked')); + $this->assertEquals('radio', pq($inputs->elements[0])->attr('type')); + } + + /** + * check that posted values overwrite preset default + */ + function test_prefill() { + global $INPUT; + $INPUT->post->set('foo', 'second'); + + + $form = new Form\Form(); + $form->addRadioButton('foo', 'label text first')->val('first')->attr('checked', 'checked'); + $form->addRadioButton('foo', 'label text second')->val('second'); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $inputs = $pq->find('input[name=foo]'); + $this->assertEquals('first', pq($inputs->elements[0])->val()); + $this->assertEquals('second', pq($inputs->elements[1])->val()); + $this->assertEquals('', pq($inputs->elements[0])->attr('checked')); + $this->assertEquals('checked', pq($inputs->elements[1])->attr('checked')); + $this->assertEquals('radio', pq($inputs->elements[0])->attr('type')); + } +} diff --git a/_test/tests/inc/form/form.test.php b/_test/tests/inc/form/form.test.php new file mode 100644 index 000000000..3ae832b2c --- /dev/null +++ b/_test/tests/inc/form/form.test.php @@ -0,0 +1,115 @@ +elements as $element) $list[] = $element->getType(); + return $list; + } + + public function balanceFieldsets() { + parent::balanceFieldsets(); + } + +} + +class form_form_test extends DokuWikiTest { + + /** + * checks that an empty form is initialized correctly + */ + function test_defaults() { + global $INPUT; + global $ID; + $ID = 'some:test'; + $INPUT->get->set('id', $ID); + $INPUT->get->set('foo', 'bar'); + + $form = new Form\Form(); + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $this->assertTrue($pq->find('form')->hasClass('doku_form')); + $this->assertEquals(wl($ID, array('foo' => 'bar'), false, '&'), $pq->find('form')->attr('action')); + $this->assertEquals('post', $pq->find('form')->attr('method')); + + $this->assertTrue($pq->find('input[name=sectok]')->length == 1); + } + + + function test_fieldsetbalance() { + $form = new TestForm(); + $form->addFieldsetOpen(); + $form->addHTML('ignored'); + $form->addFieldsetClose(); + $form->balanceFieldsets(); + + $this->assertEquals( + array( + 'fieldsetopen', + 'html', + 'fieldsetclose' + ), + $form->getElementTypeList() + ); + + $form = new TestForm(); + $form->addHTML('ignored'); + $form->addFieldsetClose(); + $form->balanceFieldsets(); + + $this->assertEquals( + array( + 'fieldsetopen', + 'html', + 'fieldsetclose' + ), + $form->getElementTypeList() + ); + + + $form = new TestForm(); + $form->addFieldsetOpen(); + $form->addHTML('ignored'); + $form->balanceFieldsets(); + + $this->assertEquals( + array( + 'fieldsetopen', + 'html', + 'fieldsetclose' + ), + $form->getElementTypeList() + ); + + $form = new TestForm(); + $form->addHTML('ignored'); + $form->addFieldsetClose(); + $form->addHTML('ignored'); + $form->addFieldsetOpen(); + $form->addHTML('ignored'); + $form->balanceFieldsets(); + + $this->assertEquals( + array( + 'fieldsetopen', + 'html', + 'fieldsetclose', + 'html', + 'fieldsetopen', + 'html', + 'fieldsetclose' + ), + $form->getElementTypeList() + ); + } + +} diff --git a/_test/tests/inc/form/inputelement.test.php b/_test/tests/inc/form/inputelement.test.php new file mode 100644 index 000000000..3257d2a89 --- /dev/null +++ b/_test/tests/inc/form/inputelement.test.php @@ -0,0 +1,58 @@ +addTextInput('foo', 'label text')->val('this is text'); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $input = $pq->find('input[name=foo]'); + $this->assertTrue($input->length == 1); + $this->assertEquals('this is text', $input->val()); + $this->assertEquals('text', $input->attr('type')); + + $label = $pq->find('label'); + $this->assertTrue($label->length == 1); + $this->assertEquals('label text', $label->find('span')->text()); + } + + /** + * check that posted values overwrite preset default + */ + function test_prefill() { + global $INPUT; + $INPUT->post->set('foo', 'a new text'); + + $form = new Form\Form(); + $form->addTextInput('foo', 'label text')->val('this is text'); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $input = $pq->find('input[name=foo]'); + $this->assertTrue($input->length == 1); + $this->assertEquals('a new text', $input->val()); + } + + function test_password() { + $form = new Form\Form(); + $form->addPasswordInput('foo', 'label text')->val('this is text'); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $input = $pq->find('input[name=foo]'); + $this->assertTrue($input->length == 1); + $this->assertEquals('this is text', $input->val()); + $this->assertEquals('password', $input->attr('type')); + + $label = $pq->find('label'); + $this->assertTrue($label->length == 1); + $this->assertEquals('label text', $label->find('span')->text()); + } +} diff --git a/_test/tests/inc/form_form.test.php b/_test/tests/inc/form_form.test.php index 02242a807..7f168b895 100644 --- a/_test/tests/inc/form_form.test.php +++ b/_test/tests/inc/form_form.test.php @@ -30,9 +30,9 @@ class form_test extends DokuWikiTest { $realoutput .= ' '; $realoutput .= 'Check'; $realoutput .= "\n"; - $realoutput .= ''; + $realoutput .= ''; $realoutput .= "\n"; - $realoutput .= ''; + $realoutput .= ''; $realoutput .= "\n"; $realoutput .= "\n\n"; return $realoutput; diff --git a/_test/tests/inc/httpclient_http.test.php b/_test/tests/inc/httpclient_http.test.php index 3446e1184..94b8e1bc1 100644 --- a/_test/tests/inc/httpclient_http.test.php +++ b/_test/tests/inc/httpclient_http.test.php @@ -289,6 +289,7 @@ class httpclient_http_test extends DokuWikiTest { * This address caused trouble with stream_select() * * @group internet + * @group flaky */ function test_wikimatrix(){ $http = new HTTPMockClient(); diff --git a/_test/tests/inc/io_deletefromfile.test.php b/_test/tests/inc/io_deletefromfile.test.php new file mode 100644 index 000000000..e86150aac --- /dev/null +++ b/_test/tests/inc/io_deletefromfile.test.php @@ -0,0 +1,15 @@ +assertTrue(io_deleteFromFile($file, "Delete\012")); + $this->assertEquals("The\012Delete01\012Delete02\012DeleteX\012Test\012", io_readFile($file)); + $this->assertTrue(io_deleteFromFile($file, "#Delete\\d+\012#", true)); + $this->assertEquals("The\012DeleteX\012Test\012", io_readFile($file)); + } + +} diff --git a/_test/tests/inc/io_readfile.test.php b/_test/tests/inc/io_readfile.test.php index e3e90cd8d..43bb7f80c 100644 --- a/_test/tests/inc/io_readfile.test.php +++ b/_test/tests/inc/io_readfile.test.php @@ -6,7 +6,7 @@ class io_readfile_test extends DokuWikiTest { * dependency for tests needing zlib extension to pass */ public function test_ext_zlib() { - if (!extension_loaded('zlib')) { + if (!DOKU_HAS_GZIP) { $this->markTestSkipped('skipping all zlib tests. Need zlib extension'); } } @@ -15,7 +15,7 @@ class io_readfile_test extends DokuWikiTest { * dependency for tests needing zlib extension to pass */ public function test_ext_bz2() { - if (!extension_loaded('bz2')) { + if (!DOKU_HAS_BZIP) { $this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension'); } } @@ -48,6 +48,11 @@ class io_readfile_test extends DokuWikiTest { $this->assertEquals("The\015\012Test\015\012", io_readFile(__DIR__.'/io_readfile/test.txt.bz2', false)); $this->assertEquals(false, io_readFile(__DIR__.'/io_readfile/nope.txt.bz2')); $this->assertEquals(false, io_readFile(__DIR__.'/io_readfile/corrupt.txt.bz2')); + // internal bzfile function + $this->assertEquals(array("The\015\012","Test\015\012"), bzfile(__DIR__.'/io_readfile/test.txt.bz2', true)); + $this->assertEquals(array_fill(0, 120, str_repeat('a', 80)."\012"), bzfile(__DIR__.'/io_readfile/large.txt.bz2', true)); + $line = str_repeat('a', 8888)."\012"; + $this->assertEquals(array($line,"\012",$line,"!"), bzfile(__DIR__.'/io_readfile/long.txt.bz2', true)); } -} \ No newline at end of file +} diff --git a/_test/tests/inc/io_readfile/large.txt.bz2 b/_test/tests/inc/io_readfile/large.txt.bz2 new file mode 100644 index 000000000..3135435f8 Binary files /dev/null and b/_test/tests/inc/io_readfile/large.txt.bz2 differ diff --git a/_test/tests/inc/io_readfile/long.txt.bz2 b/_test/tests/inc/io_readfile/long.txt.bz2 new file mode 100644 index 000000000..fb40759e6 Binary files /dev/null and b/_test/tests/inc/io_readfile/long.txt.bz2 differ diff --git a/_test/tests/inc/io_replaceinfile.test.php b/_test/tests/inc/io_replaceinfile.test.php new file mode 100644 index 000000000..d517584e1 --- /dev/null +++ b/_test/tests/inc/io_replaceinfile.test.php @@ -0,0 +1,108 @@ +markTestSkipped('skipping all zlib tests. Need zlib extension'); + } + } + + /* + * dependency for tests needing zlib extension to pass + */ + public function test_ext_bz2() { + if (!DOKU_HAS_BZIP) { + $this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension'); + } + } + + function _write($file){ + + io_saveFile($file, $this->contents); + // Replace one, no regex + $this->assertTrue(io_replaceInFile($file, "Delete\012", "Delete00\012", false, 1)); + $this->assertEquals("The\012Delete00\012Delete\012Delete01\012Delete02\012Delete\012DeleteX\012Test\012", io_readFile($file)); + // Replace all, no regex + $this->assertTrue(io_replaceInFile($file, "Delete\012", "DeleteX\012", false, -1)); + $this->assertEquals("The\012Delete00\012DeleteX\012Delete01\012Delete02\012DeleteX\012DeleteX\012Test\012", io_readFile($file)); + // Replace two, regex and backreference + $this->assertTrue(io_replaceInFile($file, "#Delete(\\d+)\012#", "\\1\012", true, 2)); + $this->assertEquals("The\01200\012DeleteX\01201\012Delete02\012DeleteX\012DeleteX\012Test\012", io_readFile($file)); + // Delete and insert, no regex + $this->assertTrue(io_replaceInFile($file, "DeleteX\012", "Replace\012", false, 0)); + $this->assertEquals("The\01200\01201\012Delete02\012Test\012Replace\012", io_readFile($file)); + } + + function test_replace(){ + $this->_write(TMP_DIR.'/test.txt'); + } + + + /** + * @depends test_ext_zlib + */ + function test_gzwrite(){ + $this->_write(TMP_DIR.'/test.txt.gz'); + } + + /** + * @depends test_ext_bz2 + */ + function test_bzwrite(){ + $this->_write(TMP_DIR.'/test.txt.bz2'); + } + + /** + * Test for a non-regex replacement where $newline contains a backreference like construct - it shouldn't affect the replacement + */ + function test_edgecase1() + { + $file = TMP_DIR . '/test.txt'; + + io_saveFile($file, $this->contents); + $this->assertTrue(io_replaceInFile($file, "Delete\012", "Delete\\00\012", false, -1)); + $this->assertEquals("The\012Delete\\00\012Delete\\00\012Delete01\012Delete02\012Delete\\00\012DeleteX\012Test\012", io_readFile($file), "Edge case: backreference like construct in replacement line"); + } + /** + * Test with replace all where replacement line == search line - must not timeout + * + * @small + */ + function test_edgecase2() { + $file = TMP_DIR.'/test.txt'; + + io_saveFile($file, $this->contents); + $this->assertTrue(io_replaceInFile($file, "Delete\012", "Delete\012", false, -1)); + $this->assertEquals("The\012Delete\012Delete\012Delete01\012Delete02\012Delete\012DeleteX\012Test\012", io_readFile($file), "Edge case: new line the same as old line"); + } + + /** + * Test where $oldline exactly matches one line and also matches part of other lines - only the exact match should be replaced + */ + function test_edgecase3() + { + $file = TMP_DIR . '/test.txt'; + $contents = "The\012Delete\01201Delete\01202Delete\012Test\012"; + + io_saveFile($file, $contents); + $this->assertTrue(io_replaceInFile($file, "Delete\012", "Replace\012", false, -1)); + $this->assertEquals("The\012Replace\01201Delete\01202Delete\012Test\012", io_readFile($file), "Edge case: old line is a match for parts of other lines"); + } + + /** + * Test passing an invalid parameter. + * + * @expectedException PHPUnit_Framework_Error_Warning + */ + function test_badparam() + { + /* The empty $oldline parameter should be caught before the file doesn't exist test. */ + $this->assertFalse(io_replaceInFile(TMP_DIR.'/not_existing_file.txt', '', '', false, 0)); + } +} diff --git a/_test/tests/inc/io_savefile.test.php b/_test/tests/inc/io_savefile.test.php new file mode 100644 index 000000000..5f387b8a1 --- /dev/null +++ b/_test/tests/inc/io_savefile.test.php @@ -0,0 +1,49 @@ +markTestSkipped('skipping all zlib tests. Need zlib extension'); + } + } + + /* + * dependency for tests needing zlib extension to pass + */ + public function test_ext_bz2() { + if (!DOKU_HAS_BZIP) { + $this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension'); + } + } + + function _write($file){ + $contents = "The\012Write\012Test\012"; + $this->assertTrue(io_saveFile($file, $contents)); + $this->assertEquals($contents, io_readFile($file)); + $this->assertTrue(io_saveFile($file, $contents, true)); + $this->assertEquals($contents.$contents, io_readFile($file)); + } + + function test_write(){ + $this->_write(TMP_DIR.'/test.txt'); + } + + /** + * @depends test_ext_zlib + */ + function test_gzwrite(){ + $this->_write(TMP_DIR.'/test.txt.gz'); + } + + /** + * @depends test_ext_bz2 + */ + function test_bzwrite(){ + $this->_write(TMP_DIR.'/test.txt.bz2'); + } + +} diff --git a/_test/tests/inc/ixr_library_date.test.php b/_test/tests/inc/ixr_library_date.test.php index f38486925..0c81e6741 100644 --- a/_test/tests/inc/ixr_library_date.test.php +++ b/_test/tests/inc/ixr_library_date.test.php @@ -2,6 +2,9 @@ require_once DOKU_INC.'inc/IXR_Library.php'; +/** + * Class ixr_library_date_test + */ class ixr_library_date_test extends DokuWikiTest { @@ -16,18 +19,24 @@ class ixr_library_date_test extends DokuWikiTest { array('2010-08-17T09:23:14Z', 1282036994), array('20100817T09:23:14Z', 1282036994), + // with timezone + array('2010-08-17 09:23:14+0000', 1282036994), + array('2010-08-17 09:23:14+00:00', 1282036994), + array('2010-08-17 12:23:14+03:00', 1282036994), + // no seconds array('2010-08-17T09:23', 1282036980), array('20100817T09:23', 1282036980), // no time array('2010-08-17', 1282003200), - //array('20100817', 1282003200), #this will NOT be parsed, but is assumed to be timestamp + array(1282036980, 1282036980), +// array('20100817', 1282003200), #this will NOT be parsed, but is assumed to be timestamp ); foreach($tests as $test){ $dt = new IXR_Date($test[0]); - $this->assertEquals($dt->getTimeStamp(),$test[1]); + $this->assertEquals($test[1], $dt->getTimeStamp()); } } diff --git a/_test/tests/inc/mailer.test.php b/_test/tests/inc/mailer.test.php index c9f7702a3..83a1ad930 100644 --- a/_test/tests/inc/mailer.test.php +++ b/_test/tests/inc/mailer.test.php @@ -197,7 +197,7 @@ class mailer_test extends DokuWikiTest { // ask message lint if it is okay $html = new HTTPClient(); - $results = $html->post('http://tools.ietf.org/tools/msglint/msglint', array('msg'=>$msg)); + $results = $html->post('https://tools.ietf.org/tools/msglint/msglint', array('msg'=>$msg)); if($results === false) { $this->markTestSkipped('no response from validator'); return; diff --git a/_test/tests/inc/parser/lexer.test.php b/_test/tests/inc/parser/lexer.test.php index d0965a13e..c50665928 100644 --- a/_test/tests/inc/parser/lexer.test.php +++ b/_test/tests/inc/parser/lexer.test.php @@ -146,7 +146,7 @@ class TestOfLexerStateStack extends DokuWikiTest { } class TestParser { - function TestParser() { + function __construct() { } function accept() { } @@ -364,7 +364,7 @@ class TestOfLexerHandlers extends DokuWikiTest { class TestParserByteIndex { - function TestParserByteIndex() {} + function __construct() {} function ignore() {} diff --git a/_test/tests/inc/parser/parser_media.test.php b/_test/tests/inc/parser/parser_media.test.php index d9a0626f5..abbcfe213 100644 --- a/_test/tests/inc/parser/parser_media.test.php +++ b/_test/tests/inc/parser/parser_media.test.php @@ -30,12 +30,21 @@ class TestOfDoku_Parser_Media extends TestOfDoku_Parser { $source = ''; $this->assertEquals(substr($url,67,64),$source); // work around random token - $a_first_part = 'assertEquals(substr($url,132,45),$a_first_part); - $this->assertEquals(substr($url,183,121),$a_second_part); + + $substr_start = 132; + $substr_len = strlen($a_first_part); + $this->assertEquals($a_first_part, substr($url, $substr_start, $substr_len)); + + $substr_start = strpos($url, '&media', $substr_start + $substr_len); + $this->assertNotSame(false, $substr_start, 'Substring not found.'); + $substr_len = strlen($a_second_part); + $this->assertEquals($a_second_part, substr($url, $substr_start, $substr_len)); + $rest = 'away.ogv'."\n"; - $this->assertEquals(substr($url,304),$rest); + $substr_start = strlen($url) - strlen($rest); + $this->assertEquals($rest, substr($url, $substr_start)); } /** @@ -58,12 +67,21 @@ class TestOfDoku_Parser_Media extends TestOfDoku_Parser { $Renderer = new Doku_Renderer_xhtml(); $url = $Renderer->externalmedia($file, null, null, null, null, 'cache', 'details', true); // work around random token - $a_first_part = ''; - $this->assertEquals(substr($url,0,34),$a_first_part); - $this->assertEquals(substr($url,40,121),$a_second_part); + + $substr_start = 0; + $substr_len = strlen($a_first_part); + $this->assertEquals($a_first_part, substr($url, $substr_start, $substr_len)); + + $substr_start = strpos($url, '&media', $substr_start + $substr_len); + $this->assertNotSame(false, $substr_start, 'Substring not found.'); + $substr_len = strlen($a_second_part); + $this->assertEquals($a_second_part, substr($url, $substr_start, $substr_len)); + $rest = 'away.vid'; - $this->assertEquals(substr($url,161),$rest); + $substr_start = strlen($url) - strlen($rest); + $this->assertEquals($rest, substr($url, $substr_start)); } @@ -84,20 +102,33 @@ class TestOfDoku_Parser_Media extends TestOfDoku_Parser { $Renderer = new Doku_Renderer_xhtml(); $url = $Renderer->externalmedia($file,null,null,null,null,'cache','details',true); - $video = '